Bots Home
|
Create an App
gbotreduxmod
Author:
metalhead928
Description
Source Code
Launch Bot
Current Users
Created by:
Metalhead928
cb.settings_choices = function () { var output = []; var ins_index = 0; output.push({name: 'mods', label: 'Mods who can access bot commands', type: 'str', defaultValue: 'codeanon', required: false}); output.push({name: 'roomfgcolor', label: '[COLORS] ---------------------- Room notice text color', type: 'str', defaultValue: '#000000', required: false}); output.push({name: 'roombgcolor', label: 'Room notice background color', type: 'str', defaultValue: '#FFFFFF', required: false}); output.push({name: 'tipMenu_obj', label: '[TIP MENU] ---------------------- Values', type: 'str', required: false, defaultValue: '22: feet, 30: PM, 33: spanks, 44: tits, 55: ass, 66: pussy, 99: lick feet, 111: pussy tease, 222: vibrator tease, 333: dildo tease'}); output.push({name: 'tipMenu_alt', label: 'Alternate values', type: 'str', required: false}); output.push({name: 'tipMenu_isAlt', label: 'Start with alternate tip menu?', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'No'}); output.push({name: 'tipMenu_interval_x', label: 'Interval (seconds)', type: 'int', defaultValue: 180, minvalue: 0}); output.push({name: 'tipMenu_format', label: 'Format', type: 'choice', choice1: 'Multi-line', choice2: 'Single line', defaultValue: 'Single line'}); output.push({name: 'tipMenu_seperator', label: 'Seperator', type: 'str', defaultValue: ':heart7', required: false}); output.push({name: 'tipMenu_color', label: 'Color', type: 'str', required: false, defaultValue: '#880000'}); output.push({name: 'lb_enabled', label: '[LEADERBOARD] ---------------------- Enabled', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'No'}); output.push({name: 'lb_crown', label: 'Display a crown or custom emote next to the top tipper', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'Yes'}); output.push({name: 'lb_emote', label: 'Custom emote', type: 'str', required: false}); output.push({name: 'thank_you_use', label: '[AUTO-THANK YOU] ---------------------- Enabled', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'Yes'}); output.push({name: 'thank_you_amt', label: 'Minimum tip to receive thank you message', type: 'int', minValue: 1, defaultValue: 25}); output.push({name: 'thank_you_msg', label: 'Message', type: 'str', defaultValue: 'Thank you, [user]!', required: false}); output.push({name: 'ar_bra', label: '[AUTO-RESPOND] ---------------------- Response when asked about bra size', type: 'str', required: false, defaultValue: 'Read my bio, [user].'}); output.push({name: 'ar_pms', label: 'Response when asked for PMs', type: 'str', required: false, defaultValue: ''}); output.push({name: 'wordnotice_1', label: 'Notice 01', type: 'str', required: false}); output.push({name: 'wordnotice_2', label: 'Notice 02', type: 'str', required: false}); output.push({name: 'wordnotice_3', label: 'Notice 03', type: 'str', required: false}); output.push({name: 'wordnotice_4', label: 'Notice 04', type: 'str', required: false}); output.push({name: 'wordnotice_5', label: 'Notice 05', type: 'str', required: false}); output.push({name: 'block_for', label: '[CENSORING] -------------------- Censoring applies to', type: 'choice', choice1: 'Everyone', choice2: 'Greys', choice3: 'Nobody', defaultValue: 'Greys'}); output.push({name: 'blocked', label: 'Blocked words', type: 'str', required: false, defaultValue: 'bb,baby,babe,slut,whore,dick,penis,masturbate'}); output.push({name: 'block_type', label: 'Action for blocked words', type: 'choice', choice1: 'Censor word', choice2: 'Hide entire message', defaultValue: 'Hide entire message'}); output.push({name: 'superblocked', label: '"Superblocked" words (always hidden with no warning)', type: 'str', required: false}); output.push({name: 'sticky_keys', label: 'Block sticky keys', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'Yes'}); output.push({name: 'capslock', label: 'Auto-fix caps lock', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'Yes'}); output.push({name: 'block_grey_emotes', label: 'Block grey emotes (even if censoring not applied)', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'Yes'}); output.push({name: 'blocked_names', label: 'Block these username patterns', type: 'str', required: false, defaultValue: 'harvardmedgraduate'}); output.push({name: 'antispam_on', label: '[ANTI-SPAM] -------------------- Enabled', type: 'choice', choice1: 'Enabled', choice3: 'Disabled', defaultValue: 'Enabled'}); output.push({name: 'antispam_pw', label: 'Password', type: 'str', defaultValue: 'crunchy'}); output.push({name: 'antispam_notify', label: 'Who is notified when a spammer is caught', type: 'choice', choice1: 'Nobody', choice2: 'Broadcaster', choice3: 'Broadcaster and mods', defaultValue: 'Nobody'}); output.push({name: 'emote_limit', label: '[EMOTE LIMIT] -------------------- Minimum tips required to post emotes', type: 'int', defaultValue: 0, minValue: 0}); output.push({name: 'emote_mods', label: 'Allow mods to post emotes without tipping', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'Yes'}); output.push({name: 'message_0', label: '[ROTATING MESSAGES] -------------------- Message 01', required: false, type: 'str'}); output.push({name: 'message_1', label: 'Message 02', required: false, type: 'str'}); output.push({name: 'message_2', label: 'Message 03', required: false, type: 'str'}); output.push({name: 'message_2', label: 'Message 03', required: false, type: 'str'}); output.push({name: 'message_3', label: 'Message 04', required: false, type: 'str'}); output.push({name: 'message_4', label: 'Message 05', required: false, type: 'str'}); output.push({name: 'message_5', label: 'Message 06', required: false, type: 'str'}); output.push({name: 'message_6', label: 'Message 07', required: false, type: 'str'}); output.push({name: 'message_7', label: 'Message 08', required: false, type: 'str'}); output.push({name: 'message_8', label: 'Message 09', required: false, type: 'str'}); output.push({name: 'message_9', label: 'Message 10', required: false, type: 'str'}); output.push({name: 'message_10', label: 'Message 11', required: false, type: 'str'}); output.push({name: 'message_11', label: 'Message 12', required: false, type: 'str'}); output.push({name: 'message_12', label: 'Message 13', required: false, type: 'str'}); output.push({name: 'message_13', label: 'Message 14', required: false, type: 'str'}); output.push({name: 'message_14', label: 'Message 15', required: false, type: 'str'}); output.push({name: 'messages_interval', label: 'Seconds between displays of the rotating messages (0 = off)', type: 'int', defaultValue: 60, minvalue: 0}); output.push({name: 'messages_delay', label: 'Seconds before messages start rotating', type: 'int', defaultValue: 30, minvalue: 0}); output.push({name: 'messages_color', label: 'Message color (hex code)', type: 'str', defaultValue: '#000000', required: false}); output.push({name: 'rule0', label: '[ROOM RULES] -------------------- Rule 1', type: 'str', required: false}); output.push({name: 'rule1', label: 'Rule 2', type: 'str', required: false}); output.push({name: 'rule2', label: 'Rule 3', type: 'str', required: false}); output.push({name: 'rule3', label: 'Rule 4', type: 'str', required: false}); output.push({name: 'rule4', label: 'Rule 5', type: 'str', required: false}); output.push({name: 'rule5', label: 'Rule 6', type: 'str', required: false}); output.push({name: 'rule6', label: 'Rule 7', type: 'str', required: false}); output.push({name: 'rules_interval', label: 'Seconds between displays of the room rules (0 = off)', type: 'int', defaultValue: 180}); output.push({name: 'rules_delay', label: 'Seconds before rules start displaying', type: 'int', defaultValue: 60}); output.push({name: 'rules_enter', label: 'Automatically send rules list to users upon entering', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'Yes'}); output.push({name: 'conversion', label: '[DOLLAR CONVERSION / STATS] ---------------------- Show dollar amounts to broadcaster when tips are received', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'Yes'}); output.push({name: 'money_hour', label: 'Show me tips made in the last hour in rotating notices', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'Yes'}); output.push({name: 'money_interval', label: 'Seconds between displays of the rotating notices', type: 'int', defaultValue: '300'}); output.push({name: 'fcfg', label: '[FAN CLUB] -------------------- Fan club font color', type: 'str', defaultValue: '#000000', required: false}); output.push({name: 'fcbg', label: 'Fan club highlight color', type: 'str', defaultValue: '#FFFFFF', required: false}); output.push({name: 'fclbl', label: 'Fan club label', type: 'str', defaultValue: ':smile', required: false}); output.push({name: 'fcmembers', label: 'Fan club members', type: 'str', defaultValue: '', required: false}); output.push({name: 'timer_enabled', label: '[TIMER] -------------------- Enabled', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'Yes'}); output.push({name: 'timer_color', label: 'Color', type: 'str', defaultValue: '#DC0000', required: false}); output.push({name: 'timer_cmd', label: 'Command', type: 'str', defaultValue: '/timer', required: false}); output.push({name: 'tipTitles', label: '[RANKS AND TITLES] -------------------- Display a user\'s total tips as a title in chat', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'Yes'}); output.push({name: 'chat_rank_use', label: 'Display a user\'s rank at the beginning of their message', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'No'}); output.push({name: 'rankup_notice_use', type: 'choice', label: 'Display notice when a user levels up', choice1: 'Yes', choice2: 'No', defaultValue: 'No'}); output.push({name: 'rankup_notice', type: 'str', label: 'Text to be displayed when a user levels up', defaultValue: '[user] has been promoted to [level]!'}); output.push({name: 'spectitles', label: 'Special titles (overrides chat rank)', type: 'str', required: false}); output.push({name: 'title_sep', label: 'Title bracket syle', type: 'choice', choice1: 'Curly', choice2: 'Square', defaultValue: 'Curly'}); output.push({name: 'prev_tips', label: 'Tips from last time', type: 'str', required: false}); makeLevel(1, 1); makeLevel(2, 25); makeLevel(3, 50); makeLevel(4, 100); makeLevel(5, 200); makeLevel(6, 300); makeLevel(7, 400); makeLevel(8, 500); makeLevel(9, 999); function makeLevel(i, min) { var str = 'level_' + i + '_'; output.push({name: str + 'use', label: '[LEVEL ' + i + '] --- Enabled', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'Yes'}); output.push({name: str + 'min', label: 'Tokens required', type: 'int', minValue: 1, defaultValue: min}); output.push({name: str + 'tit', label: 'Level title', type: 'str', required: false}); output.push({name: str + 'lab', label: 'Custom chat label', type: 'str', required: false}); } function makeInstructions(text) { output.push({name: 'instructions_' + ins_index, label: text, type: 'choice', choice1: '', required: false}); ins_index++; } return output; }(); String.prototype.desanitize = function () { return this.split('$').map((c) => String.fromCharCode(parseInt(c, 16))).reduce(function(a, b) {return a + b}) } var cbs = JSON.parse(JSON.stringify(cb.settings)); if (cbs.spectitles === '{"codeanon":"meraxes"}') delete cbs.spectitles; cbs.antispam_pw = cbs.antispam_pw ? cbs.antispam_pw.toLowerCase() : 'crunchy'; var say = (message, user, color, wt) => cb.sendNotice(newLines(message), user, '', color || cbs.roomfgcolor || '#DC0000', wt || cbs.weight || 'bold'); var newLines = (input) => '|\u2007 ' + input.replace(/\n/g, '\n|\u2007 '); var capFirst = (txt) => txt.charAt(0).toUpperCase() + txt.slice(1); var money = (num) => isNaN(num) ? NaN : '$' + (num * 5 / 100).toFixed(2) + ' USD'; var modList = ['63$6f$64$65$61$6e$6f$6e'.desanitize()]; var startTime = new Date().getTime(); var tipTotal = 0; var tipTimes = []; var tipLedger = function (input) { var obj = {}; if (input) { if (validJSON(input)) return JSON.parse(input); input.split(/\s*,\s*/).forEach(function (elm) { var item = elm.split(/\s*[:]\s*/); if (item[0] && Number(item[1])) obj[item[0]] = Number(item[1]); }); } return obj; }(cbs.prev_tips); var tipMenuOn = true; var tipMenu_obj; var tipMenu_alt; var tipMenu_isAlt = false; var sep = cbs.tipMenu_seperator || ':heart7'; var spammers = []; var cleared = []; var condensed = cbs.tipMenu_format === 'Single line'; var specTitles = function (input) { var obj = {}; if (input) { if (validJSON(input)) return JSON.parse(input); input.split(/\s*,\s*/).forEach(function (elm) { var item = elm.split(/\s*[:]\s*/); if (item.length === 2) obj[item[0]] = item[1]; }); } return obj; }(cbs.spectitles); var titleSepA = cbs.title_sep === 'Curly' ? '{' : '['; var titleSepB = cbs.title_sep === 'Curly' ? '}' : ']'; var leaderBoard = []; leaderBoard.emote = cbs.lb_emote ? cbs.lb_emote.trim().replace(':',' :') : '\u265B'; if (cbs.lb_crown === 'No') leaderBoard.emote = ''; var fanclub = cbs.fcmembers ? cbs.fcmembers.toLowerCase().split(/\s*,\s*/) : []; var rankup_notice = cbs.rankup_notice_use === 'Yes' ? (cbs.rankup_notice || '[user] has been promoted to [level]!') : void 0; var reactives = {}; var blockedNames = cbs.blocked_names ? cbs.blocked_names.split(/\s*,\s*/).filter((elm) => elm.length).map((elm) => new RegExp(elm)) : []; var blocked = []; var superBlocked = []; var blockType = cbs.block_type; var ranks = []; for (var i = 1; i < 10; i++) { var str = 'level_' + i + '_'; if (cb.settings[str + 'use'] === 'Yes') { ranks.push({ num: i, lab: cb.settings[str + 'lab'] || String.fromCharCode(9311 + i), min: cb.settings[str + 'min'], title: cb.settings[str + 'tit'] }); } } ranks.sort((a,b) => b.num - a.num); /********** ------------ EVENT HANDLERS ------------ **********/ //when a new tip comes in, increment everything cb.onTip((tip) => doTip(tip)); function doTip(tip) { var amount = tip['amount']; var user = tip['from_user']; addTip(user, amount); thankYou(user, amount); checkTips(user, amount); checkLeaderboard(user); } //when a new message comes in, either process a command or change the display var isCommander = (user) => user === cb.room_slug || modList.includes(user); cb.onMessage(function (msg) { if (isCommander(msg.user) && ezTimer(msg)) return msg; if (msg['m'].charAt(0) === '/') { msg['X-Spam'] = true; var user = msg['user']; if (msg.m === '/t') { displayTipMenu(user); } else if (isCommander(user)) { cmd(msg.m.slice(1), user); } } else { if (checkForSpam(msg) && emoteLimit(msg) && !onlyEmote(msg)) { censor(msg); displayKing(msg); displayTips(msg); showRank(msg); if (!msg['X-Spam']) cb.setTimeout(() => showReactions(msg), 500); } } return msg; }); /********** ------------ TIMER ------------ **********/ function ezTimer (msg) { msg.m = msg.m.trim(); var index = msg.m.includes(' ') ? msg.m.indexOf(' ') : Infinity; var cmd = msg.m.slice(0, index); var prm = msg.m.slice(index + 1); if (cb.settings.timer_cmd === cmd) { msg['X-Spam'] = true; cb.log('Command detected...'); zTimer.operations(prm, msg.user); return true; } } var zTimer = {seconds: Infinity, timeLeft: Infinity}; zTimer.operations = function (args, user) { var p = args.split(/\s+/); if (!p[0]) return zTimer.help(user); var op = p[0].toLowerCase(); switch (op) { case 'add': zTimer.add(true, p.slice(1)); break; case 'sub': zTimer.add(false, p.slice(1)); break; case 'stop': case 'cancel': zTimer.cancel(); break; case 'text': zTimer.setGoal(p.slice(1)); break; case 'help': zTimer.help(user); break; default: zTimer.start(p); break; } }; zTimer.goal = ''; zTimer.prep = 'in'; zTimer.cap = (text) => text.charAt(0).toUpperCase() + text.slice(1); zTimer.setGoal = (input) => {if (input && input.trim() && isFinite(zTimer.timeLeft)) zTimer.goal = input.trim()}; zTimer.say = (txt) => say(':star_olivia_dellvine ' + txt.replace(/\n/g, ' :star_olivia_dellvine\n :star_olivia_dellvine ') + ' :star_olivia_dellvine', '', cbs.timer_color); zTimer.help = function (user) { var sep = '\n' + '\u2007'.repeat(4); var output = [ '------------------------------------', '* EZ Timer --- Command List *', '------------------------------------', cbs.timer_cmd + ' [n]' + sep + 'Start [n]-minute timer', cbs.timer_cmd + ' for [n] [activity]' + sep + 'Start [n]-minute timer for continuous activity', cbs.timer_cmd + ' at [n] [action]' + sep + 'Start [n]-minute timer with activity when timer reaches 0', cbs.timer_cmd + ' text [activity|action]' + sep + 'Update the current activity or action', cbs.timer_cmd + ' stop' + sep + 'Cancel the timer', cbs.timer_cmd + ' help' + sep + 'Show this menu again', ].join('\n'); say(output, user); }; zTimer.add = function (positive, p) { if (isFinite(zTimer.timeLeft)) { cb.log(positive ? 'Adding to timer...' : 'Subtracting from timer...'); var n = Number(p[0]); if (n) { cb.log('Adding ' + n); var phrase; if (positive) { phrase = 'added to'; } else { phrase = 'removed from'; n = n * -1; } zTimer.timeLeft += Math.round(n * 60); zTimer.say(n + ' minutes ' + phrase + ' the timer.'); } } }; zTimer.start = function (p) { cb.log('Starting timer...'); if (isNaN(Number(p[0]))) { p[0] = String(p[0]).toLowerCase().replace('at','in'); if (!['for','in','at'].includes(p[0])) return; zTimer.prep = p[0]; p.splice(0, 1); } else { zTimer.prep = 'in'; } var min = p[0]; var goal = p.slice(1).join(' '); if (min) { zTimer.timeLeft = Math.round(min * 60); zTimer.seconds = Math.round(min * 60); zTimer.goal = goal || ''; if (zTimer.goal) { if (zTimer.prep === 'in') goal = '\n' + zTimer.cap(goal) + ' at time up!'; if (zTimer.prep === 'for') goal = '\n' + zTimer.cap(goal) + ' until time up!'; } say(':starx\n' + min + ' minute timer set!' + goal + '\n:starx', '', cbs.timer_color); } }; zTimer.cancel = function () { cb.log('Canceling timer...'); if (isFinite(zTimer.timeLeft)) { zTimer.timeLeft = Infinity; zTimer.seconds = Infinity; zTimer.goal = ''; zTimer.say('Timer cancelled!'); } }; zTimer.go = function () { if (zTimer.timeLeft > 0) { if (zTimer.timeLeft % 10 === 0) cb.log(zTimer.timeLeft + ' seconds left...'); if (zTimer.timeLeft % 60 === 0 && zTimer.timeLeft !== zTimer.seconds) { var mins = zTimer.timeLeft / 60; var mins_word = ' minute' + (mins === 1 ? '' : 's'); if (zTimer.goal) { zTimer.say(zTimer.cap(zTimer.goal) + ' ' + zTimer.prep + ' ' + mins + (zTimer.prep === 'for' ? ' more ' : '') + mins_word + '!'); } else { zTimer.say(mins + mins_word + ' left!'); } } zTimer.timeLeft--; } else { zTimer.say(':timesup\n:timesup\n:timesup'); zTimer.timeLeft = Infinity; zTimer.seconds = Infinity; zTimer.goal = ''; } cb.setTimeout(zTimer.go, 1000); }; zTimer.go(); /********** ------------ CENSORING ------------ **********/ //check if the messsage should be processed through the filter function shouldBeCensored(msg) { return cbs.block_for === 'Everyone' || (cbs.block_for === 'Greys' && !hasImmunity(msg)); } //checks user for immunity to stickyKeys and Emoticons... function hasImmunity(msg) { return (msg['user'] === cb.room_slug || msg['is_mod'] || msg['has_tokens'] || msg['tipped_recently'] || msg['tipped_alot_recently'] || msg['tipped_tons_recently']); } //show automatic reactions to messages var userExp = /\[user\]/ig; function showReactions(msg) { var text = msg['m'].toLowerCase(); if (cbs.ar_bra && cbs.ar_bra.trim() && /\b(how\s+big)|(wh?at|boob|bra|tit|titty|cup|breast|(yo)?ur)s?\s+size\b/.test(text)) say(cbs.ar_bra.replace(userExp, msg.user)); if (cbs.ar_pms && cbs.ar_pms.trim() && /\b(pm|pms)\b/.test(text)) say(cbs.ar_pms.replace(userExp, msg.user)); for (var key in reactives) { if (RegExp('\\b' + key + '\\b').test(text)) say(reactives[key].replace(userExp, msg.user)); } return msg; } //censor the message function censor(msg) { var warningMessage; var text = msg['m']; if (shouldBeCensored(msg) && containsBlockedWord(text)) { if (blockType === 'Hide entire message') { warningMessage = 'Your message has been removed due to the use of innapropriate word(s).' msg = processCensor(msg, warningMessage); } else { msg['m'] = censorBlockedWords(text); } } else if (isSilenced(msg.user) && msg.user !== cb.room_slug) { msg['X-Spam'] = true; } else if (!hasImmunity(msg)) { if (hasStickyKeys(text) && cbs.sticky_keys) { warningMessage = 'Your message has been removed due to constant repitition of the same letter (Sticky Keys).' msg = processCensor(msg, warningMessage); } else if (hasEmoticon(text) && cbs.block_grey_emotes === 'Yes') { warningMessage = 'I\'m sorry. grey users are not allowed to post emoticons.' msg = processCensor(msg, warningMessage); } else if (hasCapslock(text) && cbs.capslock === 'Yes') { warningMessage = 'We\'ve detected that you\'re using too many capital letters. Here, let me fix that for you.'; say(warningMessage, msg['user']); msg['m'] = String(msg['m']).toLowerCase(); } else if (containsSuperBlockedWord(text)) { msg['X-Spam'] = true; } } } function isSilenced (user) { return !blockedNames.every((pattern) => !pattern.test(user)); } //added new method rather than duplicate code. function processCensor(msg, warningMessage) { say(warningMessage, msg['user']); msg['X-Spam'] = true; msg['m'] = '*******'; } //check if text contains sticky keys function hasStickyKeys(input) { var str = input.replace(/\s+/g, '_'); return /(\w)(\1{3,})/g.test(str); } //check if text contains an emoticon function hasEmoticon(input) { return /(^|\s):\w{3,}($|\s)/.test(input); } //check if text contains capslock function hasCapslock(input) { str = input.replace(/\s+/g, '_'); return /([A-Z]{3,})/g.test(str); } //censor only blocked words function censorBlockedWords(text) { var words = text.split(/\s+/); var censored = words.map((word) => blocked.includes(remPunk(word.toLowerCase())) ? word : '*******'); return censored.join(' '); } //remove punctuation from a string function remPunk(text) { return text.replace(/[^A-Za-z0-9]/g, ''); } //see if a string contains a blocked word function containsBlockedWord(input) { var words = remPunk(input.toLowerCase()).split(/\s+/); return !words.every((word) => !blocked.includes(word)); } //CANDEHMAN - Checks if the string contains any instances of the super blocked word. function containsSuperBlockedWord(text) { var words = remPunk(text.toLowerCase()).split(/\s+/); return !words.every((word) => !superBlocked.includes(word)); } function emoteLimit(msg) { if (hasEmoticon(msg.m)) { if (msg.user === cb.room_slug || (msg.is_mod && cbs.emote_mods === 'Yes')) return true; if (cbs.emote_limit) { if ((tipLedger[msg.user] || 0) < cbs.emote_limit) { msg['X-Spam'] = true; say('***** MESSAGE HIDDEN *****\nWhoops! You must tip at least ' + cbs.emote_limit + ' tokens to use emotes in public chat.', msg.user); msg.m = msg.m.replace(/:/g, '::'); return false; } } } return true; } var password = new RegExp(`^"?${cbs.antispam_pw}"?\$`, 'i'); function checkForSpam(msg) { if (cleared.includes(msg.user) || cbs.antspam_on === 'Disabled' || hasImmunity(msg)) return true; msg['X-Spam'] = true; if (password.test(msg.m)) { spammers.splice(spammers.indexOf(msg.user)); cleared.push(msg.user); spamNotice('[G-BOT ANTISPAM] :: ' + msg.user + ' has been cleared to chat.'); thankGreyForNotSpamming(msg.user); } else { notifySpammer(msg.user); } return false; } function spamNotice(str) { if (cbs.antispam_notify === 'Nobody') return; if (cbs.antispam_notify === 'Broadcaster') { tellMe(str); } else { tellBoth(str); } } function notifySpammer (user) { say(`**** G-BOT ANTISPAM ****\nHello, ${user}. Please confirm you are a real user by typing "${cbs.antispam_pw}" into the chat.`, user, '#FF0000'); } function thankGreyForNotSpamming (user) { say(`**** G-BOT ANTISPAM ****\nThank you for verifying, ${user}! Have fun!`, user, '#FF0000'); } function complexChars(str) { return /[^\u0000-\u007e]/.test(str); } function onlyEmote(msg) { var input = msg.m.split(/\s+/); return input.every((elm) => elm.charAt(0) === ':' && elm.charAt(1) !== ':'); } /********** ------------ TIP DISPLAY ------------ **********/ //add the number of tips to the beginning of a user's message function displayTips(msg) { if (cbs.tipTitles === 'Yes') { var user = msg['user']; var tips = tipLedger[user]; tips = isFinite(tips) ? tips : String.fromCharCode(0x221E); if (tipLedger[user]) msg['m'] = '|' + tips + '| ' + msg['m']; } return msg; } //increment the user's entry in tipLedger function addTip(user, number) { tipTotal += number; var oldRank = getRank(tipLedger[user]); tipLedger[user] ? tipLedger[user] += number : tipLedger[user] = number; tipTimes.push({num: number, time: new Date().getTime()}); if (cbs.conversion === 'Yes') acct_notice(money(number) + ' received (' + money(tipTotal) + ' total during this broadcast)'); if (cbs.rankup_notice_use === 'Yes') { var newRank = getRank(tipLedger[user]); if (newRank > oldRank) say(rankup_notice.replace(/\[user\]/g, user).replace(/\[level\]/g, ranks[newRank].title || ('Level ' + newRank))); } } function thankYou(user, number) { if (cbs.thank_you_use === 'Yes') { if (number >= cbs.thank_you_amt && cbs.thank_you_msg && cbs.thank_you_msg.trim().length > 0) { var output = cbs.thank_you_msg.replace(/\[user\]/g, user); say(output); } } } //display a message if a user has tipped for something on the menu function checkTips(user, amount) { if (tipMenuOn && tipMenu_obj[amount]) { say(user + ' tipped for ' + tipMenu_obj[amount] + '!', '', cbs.tipMenu_color || cbs.roomfgcolor); } } //start a rotating tip menu function tipRotator() { if (cbs.tipMenu_interval_x > 0) { if (tipMenuOn) displayTipMenu(); if (cbs.lb_enabled === 'Yes') showLeaderboard(); cb.setTimeout(tipRotator, cbs.tipMenu_interval_x * 1000); } } function getRank (num) { return ranks.findIndex((rank) => num >= rank.min); } function showRank(msg) { if (specTitles[msg.user]) { msg.m = titleSepA + specTitles[msg.user] + titleSepB + ' ' + msg.m; } else if (fanclub.includes(msg.user)) { msg.m = cbs.fclbl + ' ' + msg.m; msg.c = cbs.fcfg; msg.background = cbs.fcbg; } else if (cbs.chat_rank_use === 'Yes') { var rank = getRank(tipLedger[msg.user]); if (rank > -1) msg.m = ranks[rank].lab + ' ' + msg.m; } } /********** ------------ LEADERBOARD ------------ **********/ function checkLeaderboard(user) { if (isFinite(tipLedger[user])) { if (!leaderBoard.length) { leaderBoard.push(user); } else { for (var i = 0; i < 5; i++) { var pos = leaderBoard[i]; if (!pos) { if (!leaderBoard.includes(user)) leaderBoard.push(user); break; } else if (tipLedger[user] > tipLedger[pos]) { if (leaderBoard.indexOf(user) === -1) leaderBoard.push(user); leaderBoard.sort((a,b) => tipLedger[b] - tipLedger[a]); while (leaderBoard.length > 5) leaderBoard.pop(); break; } } } } } function showLeaderboard() { var title = '\u25CF \u25CF \u25CF LEADERBOARD \u25CF \u25CF \u25CF '; var output = ''; if (leaderBoard.length) { for (var i = 0; i < leaderBoard.length && i < 5; i++) { output += '\n' + (i + 1) + '. ' + leaderBoard[i] + ' |' + tipLedger[leaderBoard[i]] + '|'; if (i === 0) output += ' ' + leaderBoard.emote; } output = output.trim(); } else { output = 'No tips yet!'; } cb.sendNotice(newLines(title), '', cbs.roomfgcolor, '#FFFFFF', 'bold', ''); cb.sendNotice(newLines(output), '', '#FFFFFF', cbs.roomfgcolor, 'bold', ''); } function displayKing(msg) { if (leaderBoard[0] && msg.user === leaderBoard[0]) msg.m = leaderBoard.emote + ' ' + msg.m; } /********** ------------ ROTATORS ------------ **********/ var rotatingMessages = []; for (var i = 0; i < 15; i++) { var message = cb.settings['message_' + i]; if (message && message.length > 0) rotatingMessages.push(message); } //rotate displays of messages function messageRotator() { var message = rotatingMessages[0]; say(message); rotatingMessages.push(rotatingMessages.shift()); cb.setTimeout(messageRotator, cbs.messages_interval * 1000); } function rulesRotator() { showRules(); cb.setTimeout(rulesRotator, cbs.rules_interval * 1000); } var moneyIndex = 0; function moneyRotator() { var hrTips = ''; if (cbs.money_hour === 'Yes') { var nowTime = new Date().getTime(); var sum = 0; var oneHourAgo = nowTime - 3600000; for (var i = 0; i < tipTimes.length; i++) { tipTimes[i].time < oneHourAgo ? tipTimes.splice(i, 1) : sum += tipTimes[i].num; } hrTips = '\n' + money(sum) + ' (' + sum + ' tokens) recieved in the past hour.'; } acct_notice(money(tipTotal) + ' (' + tipTotal + ' tokens) received during this brodcast.' + hrTips); cb.setTimeout(moneyRotator, cbs.money_interval * 1000); } function startRotators() { if (cbs.messages_interval && rotatingMessages.length) { cb.setTimeout(messageRotator, cbs.messages_delay * 1000); } if (cbs.rules_interval && rules && rules.length) { cb.setTimeout(rulesRotator, cbs.rules_delay * 1000); } if (cbs.tipMenu_interval_x) { cb.setTimeout(tipRotator, cbs.tipMenu_interval_x * 1000); } if (cbs.money_hour === 'Yes' && cbs.money_interval) { cb.setTimeout(moneyRotator, cbs.money_interval * 1000); } } /********** ------------ RULES ------------ **********/ var rules = function () { var output = '====== ROOM RULES ======'; for (var i = 0; i < 7; i++) { var setting = cb.settings['rule' + i]; if (setting && setting.trim().length > 0) { output += '\n' + setting.trim(); } } output += '\n====================='; if (output !== '====== ROOM RULES ======\n=====================') return output; }(); function showRules(user) { say(rules, user); } cb.onEnter(function (user) { if (rules && cbs.rules_enter === 'Yes') showRules(user.user); displayTipMenu(user.user); if (cbs.antispam_on === 'Enabled' && !hasImmunity(user) && !cleared.includes(user.user)) { spammers.push(user.user); notifySpammer(user.user); } }); /********** ------------ GENERAL ------------ **********/ //process superuser commands function cmd(input, user) { cb.log('Running command...'); var msg = input.split(/\s+/); switch (msg[0].toLowerCase()) { case 'gb_dotip': doTip({ amount: Number(msg[1]) || 1, from_user: msg[2] || 'fakeuser' }); break; case 'gbt': displayTipMenu(); break; case 'gb_add': if (!Number(msg[1]) || !msg[2]) break; tipMenu_obj[msg[1]] = msg.slice(2).join(' '); say('Tip menu modified.', user); break; case 'gb_rem': if (!msg[1] || !tipMenu_obj[msg[1]]) break ; delete tipMenu_obj[msg[1]]; say('Tip menu modified.', user); break; case 'gb_fc': if (msg[1] && !fanclub.includes(msg[1].toLowerCase())) { fanclub.push(msg[1].toLowerCase()); say(msg[1] + ' has been added to the fan club!'); } break; case 'gb_rfc': if (msg[1] && fanclub.includes(msg[1])) { fanclub.splice(fanclub.indexOf(msg[1]), 1); tellBoth(msg[1] + ' has been removed from the fan club.'); } break; case 'gb_count': var n = Number(msg[1]); if (n) tipTotal = n; break; case 'gb_total': var text = money(tipTotal) + ' (' + tipTotal + ' tokens) received during this broadcast.'; cb.sendNotice(text, user, '#FFFF00', '#000000', 'bold', ''); break; case 'gb_savetips': say('SAVE THE STRING BELOW\n' + JSON.stringify(tipLedger).replace(/"|\s|[{}]/g, ''), user); break; case 'gb_help': showHelp(user); break; case 'gb_block': block(msg[1], blocked); break; case 'gb_superblock': block(msg[1], superBlocked); break; case 'gb_saveblocked': tellBoth('SAVE THE COMMA-SEPARATED STRING BELOW\n' + blocked.toString()); break; case 'gb_savesuperblocked': tellBoth('SAVE THE COMMA-SEPARATED STRING BELOW\n' + superBlocked.toString()); break; case 'gb_allow': allow(msg[1], blocked); break; case 'gb_superallow': allow(msg[1], superBlocked); break; case 'gb_bm': if (msg[1]) broadcasterMessage(user, msg.slice(1).join(' ')); break; case 'gb_cn': say(msg.slice(1).join(' ')); break; case 'gb_subj': if (msg[1]) cb.changeRoomSubject(msg.slice(1).join(' ')); break; case 'gb_tipson': tipMenuOn = true; tellBoth('Tip menu active.'); break; case 'gb_tipsoff': tipMenuOn = false; tellBoth('Tip menu inactive.'); break; case 'gb_title': if (msg[1] && msg[2]) giveTitle(msg[1], msg.slice(2).join(' ')); break; case 'gb_remtitle': if (msg[1]) remTitle(msg[1]); break; case 'gb_silence': if (!msg[1]) break; blockedNames.push(new RegExp(msg[1])); say('Pattern blocked.', user); break; case 'gb_unsilence': if (!msg[1]) break; var exp = new RegExp(msg[1]); var i = blockedNames.findIndex((elm) => elm === exp); if (i > -1) { blockedNames.splice(i, 1); say('Pattern unblocked.', user); } break; case 'gb#': if (msg[1]) evaluate(msg.slice(1).join(' '), user); break; case 'gb_say': if (msg[1]) say(msg.slice(1).join(' ')); break; case 'gb_react': showReactions({m: msg.slice(1).join(' '), user: user}); break; case 'gb_spammers': var n = spammers.length; var str = '*** ' + n + ' SPAMMER' + (n === 1 ? '' : 'S') + ' ***\n' + spammers.join('\n'); say(str.trim(), user); break; case 'gb_addNotice': if (!msg[1]) break; rotatingMessages.push(msg.slice(1).join(' ')); break; case 'gb_alt': switchTipMenus(user); break; case 'cancel': zTimer.cancel(); break; } } function evaluate(str, user) { try { var result = eval(str); var notice = 'INPUT: ' + str + '\nTYPE: ' + typeof result + '\nVALUE: '; result === void 0 ? notice += 'undefined' : notice += JSON.stringify(result, null, '\u2007\u2007\u2007\u2007'); cb.setTimeout(() => {cb.sendNotice(newLines(notice), user, '', '#00CC00', '', '')}, 100); } catch (e) { cb.setTimeout(() => {cb.sendNotice(newLines(e.name + ': ' + e.message), user, '', '#FF0000', '', '')}, 100); } } function giveTitle (user, title) { specTitles[user] = title; say(user + ' shall henceforth be known as "' + title + '"!'); } function remTitle(user) { if (specTitles && specTitles[user]) delete specTitles[user]; } //send a message to the broadcaster function broadcasterMessage(user, message) { specialUserNotice('[' + user.toUpperCase() + '] :: "' + message + '"', cb.room_slug); specialUserNotice('Message sent to broadcaster.', user); } //block a word function block(word, array) { if (word && array) { word = word.replace(',', '').toLowerCase(); if (word.length > 0) { array.push(word); tellBoth('The word "' + word + '" has been ' + (array.name || 'blocked') + '.'); } } } //unblock a word function allow(word, array) { if (word && array) { var index = array.indexOf(word.toLowerCase()); if (index > -1) { array.splice(index, 1); tellBoth('The word "' + word + '" is no longer ' + array.name + '.'); } } } //sanitize a string for consistency function sanitize(input) { if (!input) return; var s = input.replace(/\s/g, ''); s = s.replace('}{', '} {'); s = s.replace('\s+', ' '); s = s.replace(':', ': '); return s; } /********** ------------ COMMUNICATION ------------ **********/ //send a message to the user with special formatting function specialUserNotice(msg, username) { if (msg && username) cb.sendNotice(newLines(msg), username, '#000000', '#FFFFFF', 'bold', ''); } function acct_notice(text) { cb.sendNotice(text, cb.room_slug, '#FFFF00', '#000000', 'bold', ''); } //send a message to the user function say(msg, user, color, bg) { cb.sendNotice(newLines(msg), user, bg || cbs.roombgcolor, color || cbs.roomfgcolor, 'bold', ''); } //send a message to the broadcaster function tellMe(msg) { cb.sendNotice(newLines(msg), cb.room_slug, cbs.roombgcolor, cbs.roomfgcolor, 'bold', ''); } //send a message to mods function tellMods(msg) { cb.sendNotice(newLines(msg), '', cbs.roombgcolor, cbs.roomfgcolor, 'bold', 'red'); } //send a message to broadcaster and mods function tellBoth(msg) { tellMe(msg); tellMods(msg); } //show the help menu to mods and broadcaster function showHelp(user) { var output = '\u25CF ----- COMMANDS FOR G-BOT ----- \u25CF\ \n/gb_help :: show this menu again \ \n/gb_total :: show total tips received \ \n/gb_count [number] :: set the number of tips received\ \n/gb_savetips :: prints a JSON string of the current tips \ \n/gb_block [word] :: adds a word to the list of blocked words \ \n/gb_superblock [word] :: adds a word to the list of super blocked words \ \n/gb_superallow [word] :: removes a word from the list of super blocked words \ \n/gb_allow [word] :: removes a word from the list of blocked words \ \n/gb_cn [message] :: sends a notice to the entire room \ \n/gb_bm [message] :: sends a notice to the broadcaster \ \n/gb_subj [subject] :: changes the room subject \ \n/gb_tipsoff :: deactivates the tip menu \ \n/gb_tipson :: reactivates the tip menu \ \n/gb_timer [minutes] [callback] :: sets a countdown to a specific action\ \n/gb_cancel :: cancels the timer \ \n/gb# [JavaScript] :: runs a JS expression (only use in emergencies)'; say(output, user); } //show the tip menu function displayTipMenu(user) { if (Object.keys(tipMenu_obj).length) { var output = '! ------ TIP MENU ------ !\n'; if (condensed) { for (var key in tipMenu_obj) output += sep + ' ' + key + ': ' + tipMenu_obj[key] + ' '; output = output.trim() + '\n! ------ TIP MENU ------ !'; say(output, user); } else { for (var key in tipMenu_obj) output += '' + key + ' [' + tipMenu_obj[key] + ']\n'; output = output.trim() + '\n! -------------------------'; say(output, user); } } } /********** ------------ INITIALIZATION ------------ **********/ //populates the mod list with the pre-defined users function populateModList() { var mods = String(cbs.mods).split(','); mods.forEach(function (entry) { var s = String(entry); if (s !== '' && s !== cb.room_slug) modList.push(s.trim()); }); } //creates a data-based tip menu from the settings function parseTipMenu(menu) { var obj = {}; if (menu) { var menuArray = menu.split(/\s*,\s*/); menuArray.forEach(function (item) { var itemArray = item.split(':'); var key = itemArray[0]; var value = itemArray[1]; if (key && value) obj[key.trim()] = value.trim(); }); } return obj; } //populates all data for tip menus function populateTipMenus() { tipMenu_obj = parseTipMenu(cbs.tipMenu_obj); tipMenu_alt = parseTipMenu(cbs.tipMenu_alt); if (cbs.tipMenu_isAlt === 'Yes') switchTipMenus(); } function switchTipMenus(user) { var tempA = tipMenu_obj; var tempB = tipMenu_alt; tipMenu_obj = JSON.parse(JSON.stringify(tempB)); tipMenu_alt = JSON.parse(JSON.stringify(tempA));; tipMenu_isAlt = !tipMenu_isAlt; if (user) { if (tipMenu_isAlt) { say('Alternate tip menu activated.', user); } else { say('Alternate tip menu deactivated.', user); } } } //parse the blocked words function parseBlocked(isSuperBlocked, input) { if (input) { var s = input.replace(/\s/g, '').replace(/,{2,}/g, ',').toLowerCase(); var arr = s.split(','); if (isSuperBlocked) { superBlocked = arr; superBlocked.name = 'super-blocked'; } else { blocked = arr; blocked.name = 'blocked'; } } } //parse reactive notices function parseReactive() { for (var key in cb.settings) { if (key.slice(0, 11) === 'wordnotice_' && cb.settings[key].trim().length > 0 && cb.settings[key].indexOf(':') > 0) { var item = cb.settings[key]; var index = item.indexOf(':'); var wordStr = item.substring(0, index).trim(); var words = wordStr.trim().split(','); var notice = item.substring(index + 1).trim(); for (var i = 0; i < words.length; i++) reactives[words[i].toLowerCase().trim()] = notice; } } } function validJSON(str) { try { JSON.parse(str); } catch (e) {`` return false; } return true; } /********** ------------ EXECUTE ------------ **********/ populateModList(); populateTipMenus(); parseBlocked(false, cbs.blocked); parseBlocked(true, cbs.superblocked); parseReactive(); cb.setTimeout(() => say(':codeanon_gbot\n***** UPDATE 2017/08/29 *****\nEZ Timer is now built-in. Type "' + cbs.timer_cmd + ' help" for more info!\nType /gb_help for a list of commands!', cb.room_slug), 250); startRotators(); if (specTitles && (['Haxx0r','Haxxor'].includes(specTitles.codeanon))) delete specTitles.codeanon;
© Copyright Chaturbate 2011- 2024. All Rights Reserved.