Bots Home
|
Create an App
RoomStats
Author:
bot_factory
Description
Source Code
Launch Bot
Current Users
Created by:
Bot_Factory
/* ################################################################################################################# # Custom bot for RoomTraffic # # Modules included are: RoomTraffic,Help # # Author: bot_factory # Version: 20211222.0016 ################################################################################################################# */ /* ############################## # main (version 20211220.1817) ############################## */ var botname='RoomTraffic',roomname='RoomTraffic'; /* ##################################################### # Declare Global variables and initalization function ##################################################### */ var modules={},thismod={},botmods={}; modules.names=[]; var model=cb.room_slug var debug=0; const wspc=String.fromCodePoint(0x2800),wspc2=wspc+wspc,wspc3=wspc2+wspc; cb.settings_choices=[]; function init() { modnames=modules.names.join(); sendNotice(`${wspc}Running ${botname} with the following functions enabled:\n${wspc2}${modnames}\n${wspc}Type /help for more info\n${wspc}${botname} was created by bot_factory`,"","#900000"); // sendNotice(`${wspc}Bot ${botname} courtesy of alanstuart`,model,"#900000"); for (const m of modsHandling("onInit")) {modules[m].funct("onInit","",m);} botInit(); } /* ############################# # Process Messages ############################# */ cb.onMessage(function (msg) { let c=parseMsg(msg); if (debug) {sendNotice("Debug: user="+c.user+",iscmd="+c.iscmd+",ismod="+c.ismod+",ismodel="+c.ismodel+",isgrey="+c.isgrey+",isfan="+c.isfan+",model="+model+",msg="+c.msg.m,c.user,"#ffffff","#000090","bold");} /* ####################################### # Process chat messages (non-commands) ####################################### */ if (!c.iscmd) { for (const m of modsHandling("onMessage")) { if (modules[m].funct("onMessage",c,m)) {return msg;} } return msg; } /* ####################################### # Process command messages ####################################### */ if (c.iscmd) { if (debug) {sendNotice("Debug: cmd="+c.cmd+",cpct="+c.cmdparmct+",c0="+c.cmd0+",c1="+c.cmd1+",c2="+c.cmd2+",cp1="+c.cmdparms[1],c.user,"#ffffff","#000090","bold");} for (const m of modsHandling("onCommand")) { if (modules[m].funct("onCommand",c,m)) {msg['X-Spam']=true;return msg;} } } // If it was a recognized command but not processed above, it must be syntax or permission error, // Otherwise pass through the command message unaltered (it may be used by another bot) if (c.cmd in c.cmds) {return badCommand('Syntax or Authorization error in command, type "/help" for more info',c);} else {return msg;} }); /* ############################# # Process User Entering Room ############################# */ cb.onEnter(function(user) { if (debug) {sendNotice("Debug: user "+user.user+" entered room","","#ffffff","#000090","bold");} for (const m of modsHandling("onEnter")) {modules[m].funct("onEnter",user,m);} }); /* ############################# # Process User Leaving Room ############################# */ cb.onLeave(function(user) { if (debug) {sendNotice("Debug: user "+user.user+" left room","","#ffffff","#000090","bold");} for (const m of modsHandling("onLeave")) {modules[m].funct("onLeave",user,m);} }); /* ############################# # Process User Following ############################# */ cb.onFollow(function(user) { if (debug) {sendNotice("Debug: user "+user.user+" followed","","#ffffff","#000090","bold");} for (const m of modsHandling("onFollow")) {modules[m].funct("onFollow",user,m);} }); /* ############################# # Process User unFollowing ############################# */ cb.onUnFollow(function(user) { if (debug) {sendNotice("Debug: user "+user.user+" unfollowed","","#ffffff","#000090","bold");} for (const m of modsHandling("onUnFollow")) {modules[m].funct("onUnFollow",user,m);} }); /* ############## # Process Tip ############## */ cb.onTip(function(tip) { if (debug) {sendNotice(`Debug: amt=${tip.smount},msg=${tip.message},from=${tip.from_user}`,"","#ffffff","#000090","bold");} for (const m of modsHandling("onTip")) {modules[m].funct("onTip",tip,m);} }); /* ################## # CORE FUNCTIONS # ################## /* ####################################################################### # Get the list of mods that have a handler for the event ####################################################################### */ function modsHandling(event) { let modlist=[]; modules.names.forEach(m=>{if (modules[m].events.includes(event)) {modlist.push(m)}}) return modlist; } /* ####################################################################### # Parse command parameters and user info into variables ####################################################################### */ function parseMsg(msg) { let c={}; c.msg=msg; c.origmsg=msg.m; c.user=msg.user; if (msg.is_mod||botmods[c.user]) {c.ismod=1;} else {c.ismod=0;} if (msg.has_tokens) {c.isgrey=0;} else {c.isgrey=1;} if (msg.in_fanclub) {c.isfan=1;} else {c.isfan=0;} if (c.user==model) {c.ismodel=1; c.ismod=1;} else {c.ismodel=0;} if (msg.m.substr(0,1)!=='/') {c.iscmd=0; return c;} else {c.iscmd=1} c.cmdparms=[]; c.cmdparms = notBlank(msg.m.substr(1).split(" ")); c.cmd = c.cmdparms[0]; c.cmdparmct = c.cmdparms.length-1; c.cmd0=c.cmd1=c.cmd2=c.cmd1p=c.cms2p=""; if (c.cmdparmct==0) {c.cmd0=c.cmd;} if (c.cmdparmct==1) {c.cmd1=c.cmd; c.cmd1p=c.cmd+" "+c.cmdparms[1];} if (c.cmdparmct==2) {c.cmd2=c.cmd; c.cmd2p=c.cmd+" "+c.cmdparms[1]+" "+c.cmdparms[2];} c.cmds=[]; return c; } /* ########################################################################### # Sends an error message notice in response to an invalid command message ########################################################################### */ function badCommand(badmsg,c) { cb.sendNotice('Error in command "'+c.msg.m+'"'+"\n"+badmsg,c.user,"#900000","#ffffff"); c.msg['X-Spam'] = true; return c.msg; } /* ########################################################################### # Function to facilitate splitting command message parms ########################################################################### */ function notBlank(array) { return array.filter(function(item){ return item != ""; }); } /* ##################################################################################### # Notice management # (if your bot uses this function, add "checkNotices()" into the init section) ##################################################################################### */ var notices={},notice={},lastsend=0;notice.timer=0; // function checkNotices() { const now=new Date().getTime(); if (notice.timer==0) {notice.last=now;} Object.keys(notices).forEach(n=>{ if (notices[n].interval>0) { notices[n].timeleft-=now-notice.last; if (notices[n].timeleft<=0) { showNotice(n); notices[n].timeleft+=notices[n].interval; } } }); notice.last=now; notice.timer=cb.setTimeout(checkNotices,1000); } // function addNotice(n,msg,user,interval,delay=0,fgcolor="#000090",bgcolor="#ffffff",weight="bold") { if (n in notices) {delete notices[n];} if (delay==-1) {delay=Math.floor(Math.random()*interval);} notices[n]={"message":msg,"user":user,"interval":interval*1000,"fgcolor":fgcolor,"bgcolor":bgcolor,"weight":weight,"timeleft":delay*1000}; if ((interval!==0)&&(delay!==0)) showNotice(n); } // function delNotice(n) {if (n in notices) {notices[n].interval=0;}} // function listNotices(user) { if (Object.keys(notices).length==0) {sendNotice("There are currently no Notices",user); return;} sendNotice("# List of notices",user); Object.keys(notices).forEach(n=>{ let u=notices[n].user; if (Array.isArray(u)) {u=u.join();} let m=notices[n].message; if (typeof(m)=='function') {m=m.name+"()";} sendNotice("# name="+n+", user="+u+", interval="+notices[n].interval/1000+" sec, nextnotice="+notices[n].timeleft/1000+"sec, message= "+m,user); }); } // function processUserList(ul) { let ul1=((ul.split(" ")).join("")).split(","); if (ul1.length==0) {return [`#Invalid user list: "${ul}"`]} let ul2=[]; for (u of ul1) { if (validateUserName(u)) {ul2.push(u)} else {return [`#Invalid user name: "${u}"`]} } if (ul2.includes("*")) {return ["*"];} return ul2; } // function validateUserName(n) { if (n.length>32) {return 0;} if ((n=="*")||(n=="*m")||(n=="*b")) {return 1;} if (!/^[a-zA-X0-9_]+$/.test(n)) {return 0;} return 1; } // function showNotice(n) { let m=""; if (typeof(notices[n].message)=='function') {m=notices[n].message();} else {m=notices[n].message;} let users=notices[n].user; if (!Array.isArray(users)) {users=[users];} for (u of users) { if (u=="*m") {sendNotice(m,"",notices[n].fgcolor,notices[n].bgcolor,notices[n].weight,"red");} else { if (u=="*b") {u=model;} else if (u=="*") {u="";} sendNotice(m,u,notices[n].fgcolor,notices[n].bgcolor,notices[n].weight); } } } // function sendNotice(notice,touser="",fgcolor="#000090",bgcolor="#ffffff",weight="bold",togroup="") { var now = new Date().getTime(); var wait = Math.max(lastsend+200-now,0); setTimeout(function(){cb.sendNotice(notice,touser,bgcolor,fgcolor,weight,togroup);},wait); lastsend=now+wait; } /* ##################################################################################### # Read settings for a module into modules[mod].data ##################################################################################### */ function readCBSettings(mod) { const m = modules[mod]; Object.keys(cb.settings).forEach(s=>{ let val = cb.settings[s]; let sp = s.split('_'); if (sp[0].toLowerCase()==mod.toLowerCase()) { if (typeof(val)=="string") { if ((val.toLowerCase()=="-yes-")||(val.toLowerCase()=="-true-")) {val=1;} else if ((val.toLowerCase()=="-no-")||(val.toLowerCase()=="-false-")) {val=0;} } sp.splice(0,1); if (sp[0]) { const ind=Number(sp[0]); if (Number.isInteger(ind)) { sp.splice(0,1); const vn=sp.join('_'); if (!m.data[vn]) {m.data[vn]=[];} m.data[vn][ind]=val; } else { const vn=sp.join('_'); m.data[vn]=val; } } else {m.data[s]=val;} } }) } /* ##################################################################################### # Override cb.setting_choices parameters setup in modules ##################################################################################### */ function deleteSC(scn) { cb.settings_choices.forEach((sc,i)=>{ if (sc.name.toLowerCase()==scn.toLowerCase()) {cb.settings_choices.splice(i,1); return;} }); } /* ######################################################################################### # Stub function to be run on bot initialization -- to be overridden with custom bot code ######################################################################################### */ function botInit() {} /* #################### # MODULES #################### */ /* ##################################################################################### # Module: RoomTraffic (version 20211222.0016) ##################################################################################### */ modules['RoomTraffic']={};thismod=modules['RoomTraffic'];thismod.data={};modules.names.push('RoomTraffic');thismod.name='RoomTraffic'; thismod.data.bgcol="#ffffff";thismod.data.fgcol="#b30000"; thismod.data.watchcode={"No One":0,"Mods & Fanclub Members":1,"Mods, Fanclub & Purple":2,"Mods, Fanclub, Purple & Dark Blue":3,"All users with Tokens":4,"All Users":5}; thismod.data.utcode=gen={"model":0,"mod":1,"fan":2,"dpurp":3,"lpurp":4,"dblue":5,"lblue":6,"grey":7}; thismod.data.notify = [[1,0,0,0,0,0,0,0], [1,1,1,0,0,0,0,0], [1,1,1,1,1,0,0,0], [1,1,1,1,1,1,0,0], [1,1,1,1,1,1,1,0], [1,1,1,1,1,1,1,1]]; thismod.data.emote={"E":String.fromCodePoint(0xff1d).repeat(2)+String.fromCodePoint(0x25b7).repeat(1),"L":String.fromCodePoint(0x25c1).repeat(1)+String.fromCodePoint(0xff1d).repeat(2),"F":String.fromCodePoint(0x1f525)}; thismod.data.msgpref={"E":"Welcome to the room","L":"See you again soon"}; thismod.data.color={"model":"#dc5500","grey":"#939393","lblue":"#6699aa","dblue":"#1e5cfb","lpurp":"#be6aff","dpurp":"#804baa","fan":"#009900","mod":"#dc0000"} cb.settings_choices.push( {name:`${thismod.name}_watch`,type:'choice',label:'Select which types of users that enter/leave notifications should be displayed for',required:true,defaultValue:'All Users', choice1:"No One",choice2:"All Users",choice3:"Mods & Fanclub Members",choice4:"Mods, Fanclub & Purple",choice5:"Mods, Fanclub, Purple & Dark Blue",choice6:"All users with Tokens"}, {name:`${thismod.name}_tnot`,type:'choice',label:'Select who should get notified when users enter/leave',required:true,defaultValue:'Performer and Mods', choice1:"Performer Only",choice2:"Performer and Mods",choice3:"Everyone in the Room",choice4:"No One"}, {name:`${thismod.name}_follow`,type:'choice',choice1:"-Yes-",choice2:"-No-",defaultValue:'-Yes-',label:'Display Follow Thank You Notifications?',required:true}, ); thismod.events=["onFollow","onEnter","onLeave","onInit"]; thismod.funct = function(mode,c,m) { const mod=modules[m]; if (mode=="onFollow") { if (!mod.data.follow) {return} const emote=mod.data.emote[mode.substr(2,1)]; sendNotice(wspc+emote+" Thank you for following "+emote+wspc+c.user+"!",null,"#f47321"); } else if (mode=="onEnter"||mode=="onLeave") { let n="",mnot=false; const tnot=mod.data.tnot; const watch=mod.data.watch; const watchcode=mod.data.watchcode[watch]; const ut=mod.uType(c); const utcol=mod.data.color[ut]; const utcode=mod.data.utcode[ut]; const emote=mod.data.emote[mode.substr(2,1)]; const msgpref=mod.data.msgpref[mode.substr(2,1)]; // cb.log(emote+"^"+tnot+"^"+ut+"^"+utcode+"^"+utcol+"^"+watch+"^"+watchcode+"^"+mod.data.notify[watchcode][utcode]); if (!mod.data.notify[watchcode][utcode]) {return;} if (tnot=="No One") {return;} else if (tnot=="Performer Only") {n=model} else if (tnot=="Performer and Mods") {n=model;mnot=true} let fc=utcol,bc="#ffffff"; if (utcode<5) {bc=utcol;fc="#ffffff"} let m=wspc+emote+wspc+c.user+wspc; if (n=="") {m=`${wspc}${msgpref} ${c.user} !${wspc}`} sendNotice(m,n,fc,bc,"normal"); if (mnot) {sendNotice(m,null,fc,bc,"normal","red")} } else if (mode=="onInit") { sendNotice(`${wspc}Running module RoomTraffic${wspc}\n${wspc2}** In your broadcast settings screen (gear icon next to PM tab), `+ `set the Entry and Leave notifications to None${wspc2}`,model,mod.data.bgcol,mod.data.fgcol); readCBSettings(m); } return 0; } thismod['uType'] = function(u) { mod=modules['RoomTraffic']; if (u.name==model) {return "model"} else if (u.is_mod) {return "mod"} else if (u.in_fanclub) {return "fan"} else if (u.tipped_tons_recently) {return "dpurp"} else if (u.tipped_alot_recently) {return "lpurp"} else if (u.tipped_recently) {return "dblue"} else if (u.has_tokens) {return "lblue"} else {return "grey"} } thismod.summary = "Get notifications when users enter, leave, of follow"; thismod.desc = "The performer, and optionally mods or all users will get notifications when users enter, leave, or follow\n"+ "The user types for which enter/leave notifications are displayed can be adjusted\n"+ "**Note - In your broadcast settings screen (gear icon next to PM tab), set the Entry and Leave notifications to None"; thismod.lparms = {'Enter/Leave Notification User Types': "Select which types of users that enter/leave notifications should be displayed for", 'Who should get notified when Users Enter/Leave?': "Select who should get notified when users enter/leave", 'Display Follow Thank You Notifications?': "Select whether a thank you notification should be displayed in the room for new followers"} thismod.commands = {}; /* ##################################################################################### # Module: Help (version 20211222.0016) ##################################################################################### */ modules['Help']={};thismod=modules['Help'];thismod.data={};modules.names.push('Help');thismod.name='Help'; thismod.data.fgcol="#000000";thismod.data.bgcol="#00ee00"; thismod.cmd="help"; thismod.events=["onCommand"]; thismod.funct = function(mode,c,m) { mod=modules[m]; if (mode=="onCommand") { if ((c.cmd==mod.cmd)||(c.cmd=="h")||(c.cmd=="?")) { c.cmds[c.cmd]=1; if (c.cmdparmct==0) { let h=`${wspc} Help for Bot ${botname}`; if (bothelp&&(typeof(bothelp)=="string")) {bothelp.split("\n").forEach(l=>{h+=`\n ${wspc} ${l}`})}; if (modules.names.length>0) { h+="\n"+wspc+" This Bot includes the following functions: \n"; for (const m of modules.names) { h+=` ${wspc} > "${m}"`; if (m.summary) {h+=` - ${m.summary}`;} h+=` \n`; } h+=wspc+" For help on one of these functions, type \"/help [function]\""; } sendNotice(h,c.user,mod.data.fgcol,mod.data.bgcol,"normal"); return 1; } else if (c.cmdparmct==1) { let cm = c.cmdparms[1]; if (cm!=='*') { let mfound=0; for (const m of modules.names) { if ((m==cm)||(m.toLowerCase()==cm)) {mfound=1;cm=m;} else if (modules[m].cmd) {if (modules[m].cmd.toLowerCase()==cm) {mfound=1;cm=m;}} } if (!mfound) {badCommand(`Function "${cm}" not found. Type "/help" for the list of functions in this Bot`,c); return 1;} let h1=` ${wspc} Help for function "${cm}"`; let cmod=modules[cm]; if (cmod.summary) {h1+=` (${cmod.summary})`;} let h2=""; if (cmod.desc) {cmod.desc.split("\n").forEach(l=>{h2+=` ${wspc} ${l}\n`});} if (cmod.commands && Object.keys(cmod.commands).length) { h2+=wspc2+" Commands: \n"; Object.keys(cmod.commands).forEach(c=>{ let nc=c; let mo=""; if (c.substr(0,1)=='*') {nc=c.substr(1);mo="(model/mods only)"} h2+=` ${wspc} > "${nc}" - ${cmod.commands[c]} ${mo} ${wspc}\n` }); } if (cmod.lparms && Object.keys(cmod.lparms).length) { h2+=wspc2+"\n ${wspc} Launch Parms: \n"; Object.keys(cmod.lparms).forEach(c=>{h2+=` ${wspc} > "${c}" - ${cmod.lparms[c]} ${wspc}\n`}); } if (h2=="") {sendNotice("No help found for function "+cm,c.user,mod.data.fgcol,mod.data.bgcol,"normal");} else {sendNotice(`${h1}\n${h2}`,c.user,mod.data.fgcol,mod.data.bgcol,"normal");} return 1; } else { let h=`Custom bot for <a href="https://chaturbate.com/${roomname}" style="color:#8888ff;text-decoration:underline;">`+ `${roomname}</a>'s room. Current modules included are: ${modnames}<br>`; for (const m of modules.names) { let mod=modules[m]; let mdesc=""; if (mod.summary) {mdesc=" - "+mod.summary;} h+=`<br><span style="font-style:italic;font-weight:bold;text-decoration:underline;color:#0000ff;">${m}</span><b>${mdesc}</b><br>`; if (mod.desc) {mod.desc.split("\n").forEach(l=>{h+=`${l}<br>`});} if (mod.commands && Object.keys(mod.commands).length) { h+=`<span style="text-decoration:underline;font-style:italic;font-weight:bold;color:#000000;">Commands</span><br>`; Object.keys(mod.commands).forEach(c=>{ let nc=c; let mo=""; if (c.substr(0,1)=='*') {nc=c.substr(1);mo="(model/mods only)"} h+=` > <span style="font-style:italic;color:#000000;font-weight:bold;">${nc}</span>`+ ` ${modules[m].commands[c]} ${mo}<br>`; }); } if (mod.lparms && Object.keys(mod.lparms).length) { h+=`<span style="text-decoration:underline;font-style:italic;font-weight:bold;color:#000000;">Launch Parameters</span><br>`; Object.keys(mod.lparms).forEach(c=>{ h+=` > <span style="font-style:italic;color:#000000;font-weight:bold;">${c}</span>`+ ` ${modules[m].lparms[c]}<br>`; }); } } sendNotice(`Copy this code to the bot description: ${h}`,c.user,"","","normal"); return 1; } } } } return 0; } thismod.summary = "get help on Bot functions and commands", thismod.desc = "Get help by typing /help, /h, or /?", thismod.commands = {'/h': "Get help on the Bot, and a list of all functions in the bot", '/h [function]': 'Get help on one of the functions in the bot, including it\'s commands', '/h *': "Display an auto-genertaed html description of the bot, that can be cut and paste into the Bot's description screen" }; /* ############ # BOT CODE ############ */ //debug=1; bothelp="RoomTraffic by bot_factory"; /* ################################################ # AFTER MODULES HAVE BEEN PROCESSED, RUN INIT # ################################################ */ init();
© Copyright Chaturbate 2011- 2025. All Rights Reserved.