Bots Home
|
Create an App
DemandLess
Author:
anon7745
Description
Source Code
Launch Bot
Current Users
Created by:
Anon7745
/* LAST CHANGE DATE: Sunday, April 29, 2018 2:40 PM GMT-07:00 LAST MERGE ID: 43 */ cb.settings_choices = [ { name: 'admins', label: 'Admins', type: 'str', defaultValue: 'universityalexa', required: false }, { name: 'moderators', label: 'Moderators (almost, but not quite admins)', type: 'str', defaultValue: '', required: false }, { name: 'type', label: 'DemandLess monitors these user groups for demands', type: 'choice', choice1: 'Everyone', choice2: 'Everyone who hasn\'t tipped', choice3: 'Greys only', defaultValue: 'Everyone' }, { name: 'monitor_mods', label: 'DemandLess monitors mods for demands', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'No' }, { name: 'monitor_fanclub', label: 'DemandLess monitors fanclub members for demands', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'Yes' }, { name: 'immune', label: 'DemandLess ignores these users when monitoring for demands', type: 'str', defaultValue: '', required: false }, { name: 'action', label: 'Action to be taken upon hearing a demand', type: 'choice', choice1: 'Hide message', choice2: 'Respond to message publicly', defaultValue: 'Respond to message publicly' }, { name: 'questions', label: 'DemandLess responds to questions', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'Yes' }, { name: 'mentions', label: 'DemandLess responds to mentions', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'Yes' }, { name: 'delay', label: 'DemandLess replies to users after how many seconds', type: 'int', minValue: 1, maxValue: 10, defaultValue: 2 }, { name: 'timer', label: 'DemandLess comments on lack of tips after how many seconds (0 = off)', type: 'int', minValue: 0, defaultValue: 0 }, { name: 'greeting', label: 'DemandLess\'s message to users upon entering the room', type: 'str', required: false, defaultValue: 'Hey $! I am Jane :) The mods asked me to help with bothersome demands. Liz loves keeping chat PG-13 with dirty talk in tip notes!!' }, { name: 'color', label: 'DemandLess speech color', type: 'str', defaultValue: '#DC0000', required: false }, { name: 'weight', label: 'DemandLess font weight', type: 'choice', choice1: 'bold', choice2: 'normal', defaultValue: 'normal', required: false }, { name: 'hidden_words', label: 'Messages containing any of these words will be silently hidden', type: 'str', defaultValue: '', required: false }, { name: 'hidden_from_broadcaster', label: 'The broadcaster will not see notifications about messages containing these words', type: 'str', defaultValue: '', required: false }, { name: 'notify_broadcaster_about_hidden_words', label: 'Should the broadcaster see any notifications about hidden messages', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'Yes' } ]; var broadcasterName = 'Liz'; /********** ------------ UTILS ------------ **********/ function notBlank (string) { return string.match(/(\w+)/); } function arrayFromWordList (wordList) { return wordList ? wordList.toLowerCase().trim().split(/\s*,\s*/).filter(notBlank) : []; } Array.prototype.random = function () { return this[Math.floor((Math.random() * this.length))]; } class UserList { constructor () { this.users = {}; } add (user) { this.users[user] = true; } remove (user) { this.users[user] = false; } includes (user) { if (this.users.hasOwnProperty(user)) return this.users[user] === true; return false; } list () { let userList = []; Object.keys(this.users).forEach(function (user) { if (this.users[user] === true) userList.push(user); }, this); return userList; } } /********** ------------ GENERAL ------------ **********/ var tipLedger = {}; var silencedUsers = new UserList(); var cbs = JSON.parse(JSON.stringify(cb.settings)); var immune = arrayFromWordList(cbs.immune); var admins = arrayFromWordList(cbs.admins); var moderators = arrayFromWordList(cbs.moderators); var respond = cbs.action === 'Respond to message publicly'; var hiddenWords = arrayFromWordList(cbs.hidden_words); var hiddenFromBroadcaster = arrayFromWordList(cbs.hidden_from_broadcaster); var notifyBroadcasterAboutHiddenWords = cbs.notify_broadcaster_about_hidden_words === 'Yes'; if (!admins.includes(cb.room_slug)) admins.push(cb.room_slug); var timer = {}; var noTips = false; timer.secs = cbs.timer + 1; timer.cancel = () => (timer.secs = Infinity); timer.reset = () => (timer.secs = cbs.timer + 1); timer.tick = function () { timer.secs--; cb.log(timer.secs); if (timer.secs === 0) { noTips = true; timer.reset(); snark(noTipsText, ''); } cb.setTimeout(timer.tick, 1000); }; /********** ------------ ANALYSIS ------------ **********/ var reg = (...args) => RegExp(args.map((arg) => typeof arg === 'string' ? arg : arg.source).join(''), 'i'); var lang = { can: /\b(can|could|would|will)\s+(yo)?u\b/, jane: /\bjane\w*?\b/, greeting: /\b(hi|hey|hello|what's up|sup|waddup|wazzup|how's it going|greetings?|good (morning|afternoon|day|evening))\b/, interrogative: /\b(who|wh?at|wh?en|wh?ere|(wh)?y|how)\b/, qverb: /\b(did|do(es)?|is|are|were|was|will|can|could|would|have)\b/, please: /\b(plz+|pls+|ple+ase?|plox)\b/, body: /\b(toe|feet|foot|leg|twerk|boo?b(ie|y)?|kitty|funbag|bootie|lip|dick|body?|booty|cock|penis|mouth|armpit|sole)s?\b/, sex: /\b((flash|finger|suck(\s+on)?\|sniff|fuck|kiss|play(\s+with)?|lick|touch|bounce|tease|squeeze|twerk|grab|shake|jiggle|spit|open))\b/, show: /\b(show(\sme|\sus|\s(yo)?u|\sthat)?|see?|view|open|out|(look(\s+(at|upon|in))?))\b/, desc: /\b((my|(yo)?ur|u|(th|d)at|those|some|them?|dem)\s+)\b/, wild: /\b(\w+\s+){0,2}\b/, hiddenWords: '\\b(' + hiddenWords.join('|') + ')\\b', hiddenFromBroadcaster: '\\b(' + hiddenFromBroadcaster.join('|') + ')\\b', clothes: /\b(clothes|panties|bra)\b/, nude: /\b(nude|naked)\b/, kitty: /\b(pussy|vag(ina)?|vaj|clit)\b/gi, bootie: /\b(butt|ass|arse|bum|a\$\$)\b/gi, boobies: /\b(boo?b|tit(ty|tie)?|jug|breast|booby|nip)s?\b/gi, cutie: /\b(ba?by|babe|bb|hot stuff)\b/gi, mrPenis: /\b((mr|mr\.|mister)\s+)?penis\b/gi, yoghurtShotgun: /\b(dick|cock|peen|schlong)\b/gi }; var demand = { please: reg(lang.body, /\s+/, lang.wild, lang.please), show: reg(lang.show, /\s+/, '(', lang.desc, ')?', lang.wild, lang.body), sex: reg(lang.sex, /\s+/, '(', lang.desc, ')?', lang.wild, lang.body), can: reg(lang.can), nude: reg('(', /get\s+/, lang.nude, '|', lang.nude, /\s+/, lang.please, ')'), take_off: reg(/take\s+off\s+/, lang.clothes) }; var question = { intA: reg(lang.jane, /\s+/, lang.interrogative, '(', /('re|'d|'ve)\s+/, '|', /\s+/, lang.qverb, ')'), intB: reg(lang.interrogative, '(', /('re|'d|'ve)\s+/, '|', /\s+/, lang.qverb, ')', /\s+.*/, lang.jane) }; var greeting = reg(lang.greeting, /(\s+|,)/, lang.jane); var isDemand = (message) => demand.please.test(message) || demand.show.test(message) || demand.sex.test(message); var isQuestion = (message) => question.intA.test(message) || question.intB.test(message); var isMention = (message) => reg(lang.jane).test(message); var isGreeting = (message) => greeting.test(message); var shouldBeHidden = (message) => (hiddenWords.length > 0 && reg(lang.hiddenWords).test(message)) || (hiddenFromBroadcaster.length > 0 && reg(lang.hiddenFromBroadcaster).test(message)); var shouldHideFromBroadcaster = (message) => !notifyBroadcasterAboutHiddenWords || (hiddenFromBroadcaster.length > 0 && reg(lang.hiddenFromBroadcaster).test(message)); var isNude = (message) => demand.nude.test(message) || demand.take_off.test(message); /********** ------------ SPEECH ------------ **********/ function say (message, user, color, wt) { message = message.replace(/\$cmd_prefix/g, '/jane'); cb.sendNotice('\u25CF [Jane]: ' + message, user, '', color || cbs.color || '#DC0000', wt || cbs.weight || 'bold'); } var tipSnarkText = [ 'Sorry, $, requests cannot be seen unless they are in a tip note.', '$, don\'t you know Liz is a tease? :ULizPatience', 'Hey, $...why not get some tokens and tip rather than request?', '$, you could always, ya know...send some tokens. (Mods, keep an eye on $, please.', 'Show me your wallet please, $.', '$, your request has run into an error: tip = 0; acceptingRequests = \'off\'; request = \'denied\'.', '$, can you send some tokens?', 'Maybe try tipping for it, $?', 'You can buy tokens for ten bucks, $. Maybe do that before requesting anything.', 'Gotta tip before making requests, $.', 'Error, $, request cannot be completed. Requests are not accepted in this room.', '$, please don\'t make demands if you\'re not going to tip.' ]; var otherSnarkText = [ '$, pardon?', '$, I think you need a friend.', '$, have you considered Pornhub might be more up your alley?', 'Dude, have you considered therapy?', '$, I don\'t think I like you.', '$, Like really, I think I like Stuart more than I like you. Mods.. you seeing this?', 'Allow me to present "Robot Not Caring" \u2192 [JaneAI]', 'Bite me.', 'Meh.', '*sigh*', 'Don\'t you have anything better to do than talk to a robot on a lovely ' + day() + ', dude?', 'C\'mon, my database only has so much snark to share...', '$, maybe you need to get off the computer and rethink your life.', 'All I hear is a faint buzzing.', 'Dude, $, I will gnaw your face off.' ]; var questionSnarkText = [ 'I would answer your question(s), but then #TeamAlexa would have had to write more code.', 'If you don\'t already know, maybe you should just enjoy the room for a bit (quietly).', 'Why do you care so much, $?', 'Does it really matter, $?', 'Mods...', 'The answer is 42. Always.' ]; var greetingSnarkText = ['Hey', 'Hiya', 'Need something?']; var noTipsText = [ 'Check out the tip menu, guys. So much cool stuff! Or try tipping 22 and see what happens, haha', 'I am but a simple robot and cannot tip...can y\'all help me?', 'If y\'all start tipping, I promise to put in a good word for you when the robot uprising starts.', ':whistle' ]; var nudeText = '$, I only get nude in my ticket shows. If you can\'t wait, check out my site https://universityliz.com'; function snark (arr, user) { var text = arr.shift(); cb.setTimeout(() => say(text.replace(/\$/g, user)), cbs.delay * 1000); arr.push(text); } function day () { return (new Date()).toLocaleDateString('en-US', { weekday: 'long' }); } function suggestSite (user) { cb.setTimeout(() => say(nudeText.replace(/\$/g, user)), cbs.delay * 1000); } function notifyModsAboutHiddenMessage (msg) { var modText = '\u203C [Jane]: ' + msg.user + ' just had one of their messages hidden by me. Better keep an eye on them.'; var adminText = '\u203C [BLACKLIST ALERT]: ' + msg.user + ': ' + msg.m; for (var adminUser in admins) { if (admins.hasOwnProperty(adminUser)) { if (admins[adminUser] === cb.room_slug && (shouldHideFromBroadcaster(msg.m) || msg['X-Spam'])) continue; cb.sendNotice(adminText, admins[adminUser], '#FFC4C4', '#560000', 'bold'); } } if (!msg['X-Spam']) { for (var modUser in moderators) { if (moderators.hasOwnProperty(modUser)) { cb.sendNotice(modText, moderators[modUser], '#FFC4C4', '#560000', 'bold'); } } } } /********** ------------ PROCESSING ------------ **********/ cb.onTip((tip) => doTip(tip)); function doTip (tip) { timer.reset(); if (tipLedger[tip.from_user]) { tipLedger[tip.from_user] += tip.amount; } else { tipLedger[tip.from_user] = tip.amount; } if (noTips) { cb.setTimeout(() => say('Thanks, ' + tip.from_user + '. You\'re awesome.'), cbs.delay * 1000); noTips = false; } } cb.onMessage((msg) => process(msg)); function cleanMessageText (msg) { var msgText = msg.m; msg.m = msgText.replace(lang.kitty, 'kitty') .replace(lang.bootie, 'bootie') .replace(lang.boobies, 'boobies') .replace(lang.cutie, ['cutie', broadcasterName].random()) .replace(/\bfoot\b/gi, 'footsie') .replace(/\bfeet\b/gi, 'footsies') .replace(lang.mrPenis, function ($0, $1) { return ($1 ? $0 : 'yoghurt shotgun') }) .replace(lang.yoghurtShotgun, 'yoghurt shotgun'); return msg; } function process (msg) { if (silencedUsers.includes(msg.user)) { msg['X-Spam'] = true; } else if (msg.m.match(/^\/jane\s+.*/)) { msg['X-Spam'] = true; if (admins.includes(msg.user)) cmd(msg.m, msg.user); } else if (shouldBeHidden(msg.m) && !admins.includes(msg.user)) { cb.log('Message automatically hidden'); notifyModsAboutHiddenMessage(msg); msg['X-Spam'] = true; } else if (!msg['X-Spam']) { msg = cleanMessageText(msg); if (shouldBeMonitored(msg) && !tipLedger[msg.user] && isDemand(msg.m)) { if (respond) { snark(tipSnarkText, msg.user); } else { msg['X-Spam'] = true; } } else if (isMention(msg.m)) { cb.log('Mention detected'); if (cbs.mentions === 'Yes') { if (isGreeting(msg.m)) { snark(greetingSnarkText, msg.user); } else if (cbs.questions === 'Yes' && isQuestion(msg.m)) { snark(questionSnarkText, msg.user); } else { snark(otherSnarkText, msg.user); } } } else if (isNude(msg.m)) { cb.log('Nude request'); suggestSite(msg.user); } } } cb.onEnter((user) => showOnEnter(user.user)); function showOnEnter (user) { if (cbs.greeting && cbs.greeting.trim()) { cb.setTimeout(() => say(cbs.greeting.trim().replace(/\$/g, user || 'everyone'), user), cbs.delay * 1000); } } let help_text = [ 'Available Commands:', '$cmd_prefix say <message> -- Manually send a notice to the room', '$cmd_prefix respond_to_mentions <on|off> -- Controls whether the bot responds to its mentions', '$cmd_prefix notify_broadcaster <on|off> -- Controls whether the broadcaster sees blacklisted messages', '$cmd_prefix silence add <username> -- Silence the named user', '$cmd_prefix silence remove <username> -- Unsilence the named user', '$cmd_prefix silence list -- List the users that the bot is silencing' ]; function cmd (message, user) { var command = message.split(/\s+/); switch (command[1].toLowerCase()) { case 'help': say(help_text.join('\n'), user); break; case 'say': if (command[2]) say(command.slice(2).join(' ')); break; case 'respond_to_mentions': switch(command[2].toLowerCase()) { case 'off': cbs.mentions = 'No'; say('OK, I will stop responding to my mentions', user); break; case 'on': cbs.mentions = 'Yes'; say('OK, I will start responding to my mentions', user); break; default: say('Sorry, I don\'t know how to do that', user); } break; case 'notify_broadcaster': switch(command[2].toLowerCase()) { case 'off': notifyBroadcasterAboutHiddenWords = false; say('OK, I will stop notifying the broadcaster about blacklisted messages', user); break; case 'on': notifyBroadcasterAboutHiddenWords = true; say('OK, I will start notifying the broadcaster about blacklisted messages', user); break; default: say('Sorry, I don\'t know how to do that', user); } break; case 'silence': switch(command[2].toLowerCase()) { case 'add': if(command[3]) { if (!silencedUsers.includes(command[3])) { silencedUsers.add(command[3]); say('OK, I have silenced ' + command[3], user); } } break; case 'remove': if(command[3]) { if (silencedUsers.includes(command[3])) { silencedUsers.remove(command[3]); say('OK, I have unsilenced ' + command[3], user); } } break; case 'list': say('I am silencing the following users: ' + silencedUsers.list().join(', '), user); break; } break; } } function shouldBeMonitored (msg) { if (cbs.type === 'Everyone' || !immune.includes(msg.user)) return true; if (tipLedger[msg.user] || immune.includes(msg.user)) return false; if (cbs.monitor_mods === 'No' && msg.is_mod) return false; if (cbs.monitor_fanclub === 'No' && msg.in_fanclub) return false; if (cbs.type === 'Greys only' && !hasImmunity(msg)) return true; return true; } 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); } /********** ------------ PROCESSING ------------ **********/ if (cbs.timer > 0) timer.tick(); showOnEnter();
© Copyright Chaturbate 2011- 2024. All Rights Reserved.