Bots Home
|
Create an App
Peep show
Author:
loulouw
Description
Source Code
Launch Bot
Current Users
Created by:
Loulouw
/** * Public Peep Show 0.5-r1 * Written by lactose_intolerant, 2014 */ var util = new (function( ) { this.map = function( list, transform ) { var result = []; for (var i = 0; i < list.length; ++i) result.push( transform( list[i] ) ); return result; } var secondsInAMinute = 60; var secondsInAnHour = 60 * secondsInAMinute; var splitSeconds = function( seconds ) { var hours = 0; var minutes = 0; if (seconds >= secondsInAnHour) hours = Math.floor( seconds / secondsInAnHour ); seconds = seconds - hours * secondsInAnHour; if (seconds >= secondsInAMinute) minutes = Math.floor( seconds / secondsInAMinute ); seconds = Math.floor( seconds - minutes * secondsInAMinute ); return { 'seconds' : seconds, 'minutes' : minutes, 'hours' : hours }; } this.createReadableDuration = function( seconds ) { parts = splitSeconds( seconds ); var components = []; if (parts.hours > 0) components.push( parts.hours + ":" ); components.push( parts.minutes + ":" ); components.push( parts.seconds ); return components.join( "" ); } this.createReadableDuration2 = function( seconds ) { parts = splitSeconds( seconds ); var components = []; if (parts.hours > 0) components.push( parts.hours + " hours" ); if (parts.minutes > 0) components.push( parts.minutes + " minutes" ); if (components.length == 0 || parts.seconds > 0) components.push( parts.seconds + " seconds" ); return components.join( ", " ); } this.parseDurationString = function( str ) { var match = /(?:(\d+)h)?\s*(?:(\d+)m)?\s*(?:(\d+)s)?/.exec( str ); if (match == null) return null; if (match[1] == null && match[2] == null && match[3] == null) return null; var seconds = 0; if (match[1] != null) seconds += parseInt( match[1] ) * secondsInAnHour; if (match[2] != null) seconds += parseInt( match[2] ) * secondsInAMinute; if (match[3] != null) seconds += parseInt( match[3] ); return seconds; } this.getTimeSinceEpochInSeconds = function( ) { return (new Date( )).valueOf( ) / 1000.0; } this.mergeObjects = function( a, b ) { var result = {}; for (k in a) result[k] = a[k]; for (k in b) result[k] = b[k]; return result; } this.randomArrayItem = function( array ) { var i = Math.floor( Math.random( ) * array.length ); return array[i]; } })( ); var Events = function( names ) { var handlers = {}; var init = function( ) { for (var i = 0; i < names.length; ++i) handlers[names[i]] = []; } this.add = function( event, handler ) { handlers[event].push( handler ); } this.raise = function( event /*, *args */ ) { var raiseArgs = Array.prototype.slice.call( arguments, 1 ); var rval; for (var i = 0; i < handlers[event].length; ++i) rval = handlers[event][i].apply( null, raiseArgs ); return rval; } init( ); }; var platform = new (function( ) { for (var k in cb) this[k] = cb[k]; var _this = this; var events = new Events( ["onMessage", "onEnter", "onLeave", "onTip", "onDrawPanel"] ); var isOnMockPlatform = !!cb.cbUsers; this.users = {}; var init = function( ) { cb.onMessage( cbOnMessage ); cb.onDrawPanel( cbOnDrawPanel ); cb.onTip( cbOnTip ); if (!isOnMockPlatform) { cb.onEnter( cbOnEnter ); cb.onLeave( cbOnLeave ); } } var addUser = function( cbUser ) { _this.users[cbUser.user] = cbUser; } var removeUserByName = function( username ) { delete _this.users[username]; } this.isUserPresent = function( username ) { return username in _this.users; } this.getUserByName = function( username ) { return _this.users[username]; } this.onMessage = function( handler ) { events.add( "onMessage", handler ); } this.onEnter = function( handler ) { events.add( "onEnter", handler ); } this.onLeave = function( handler ) { events.add( "onLeave", handler ); } this.onDrawPanel = function( handler ) { events.add( "onDrawPanel", handler ); } this.onTip = function( handler ) { events.add( "onTip", handler ); } this.fakeLeave = function( usernameOrObj ) { var cbUser = usernameOrObj; if (typeof usernameOrObj == "string") cbUser = createFakeUserObj( usernameOrObj ); cbOnLeave( cbUser ); } this.fakeEnter = function( usernameOrObj ) { var cbUser = usernameOrObj; if (typeof usernameOrObj == "string") cbUser = createFakeUserObj( usernameOrObj ); cbOnEnter( cbUser ); } this.setInterval = function( func, timeout ) { cb.setTimeout( function( ) { cb.setTimeout( arguments.callee, timeout ); try { func( ); } catch (e) { handleException( "onTimeout", e ); } }, timeout ); } var createFakeUserObj = function( name ) { return { "user" : name, "in_fanclub" : false, "has_tokens" : 0, "is_mod" : false, "tipped_recently" : false, "gender" : "m" }; } var cbOnMessage = function( cbMsg ) { try { var cbUser = util.mergeObjects( cbMsg, {} ); delete cbUser.c; delete cbUser.m; delete cbUser.f; updateUser( cbUser ); events.raise( "onMessage", cbMsg ); } catch (e) { handleException( "onMessage", e ); } return cbMsg; } var cbOnEnter = function( cbUser ) { try { addUser( cbUser ); events.raise( "onEnter", cbUser ); } catch (e) { handleException( "onEnter", e ); } } var cbOnLeave = function( cbUser ) { try { removeUserByName( cbUser.user ); events.raise( "onLeave", cbUser ); } catch (e) { handleException( "onLeave", e ); } } var cbOnTip = function( cbTip ) { try { var cbUser = { "user" : cbTip.from_user, "in_fanclub" : cbTip.from_user_in_fanclub, "has_tokens" : cbTip.from_user_has_tokens, "is_mod" : cbTip.from_user_is_mod, "tipped_recently" : cbTip.from_user_tipped_recently, "gender" : cbTip.from_user_gender }; updateUser( cbUser ); events.raise( "onTip", cbTip ); } catch (e) { handleException( "onTip", e ); } } var updateUser = function( cbUser ) { if (!_this.isUserPresent( cbUser.user )) _this.fakeEnter( cbUser ); else addUser( cbUser ); } var cbOnDrawPanel = function( ) { try { return events.raise( "onDrawPanel" ); } catch (e) { handleException( "onDrawPanel", e ); } } this.announce = function( msg ) { _this.chatNotice( msg, '', '#FFFFFF', '#000000', 'bold' ); } this.notify = function( username, msg ) { _this.chatNotice( msg, username, '#FFFFFF', '#000000', 'bold' ); } handleException = function( eventName, e ) { var msg = "<EXCEPTION>: \"" ; if ('message' in e) msg += e.message; else msg += e; msg += "\""; msg += " <EVENT>: " + eventName; if ('trace' in e) msg += " <TRACE>: " + e.stack; cb.log( msg ); } init( ); })( ); var Goal = function( amount, optDescription ) { var _this = this; this.amount = amount; this.received = 0; this.description = optDescription || ""; this.update = function( amount, optDescription ) { _this.amount = amount; if (typeof optDescription == 'string') this.description = optDescription; } } var Viewer = function( username ) { this.username = username; this.free = false; this.timeLeft = 0; this.lastNotifiedAt = 0; } var CommandParser = function( ) { var commands = []; var init = function( ) { platform.onMessage( cbOnMessage ); } this.register = function( key, handler, optModelOnly ) { commands.push( { 'key' : key, 'model' : !!optModelOnly, 'handler' : handler } ); } var cbOnMessage = function( cbMsg ) { var key = getKey( cbMsg.m ); var cmd = findCommand( cbMsg.user, key ); if (!!cmd) { cbMsg['X-Spam'] = true; cmd.handler.apply( null, [cbMsg.user].concat( getCommandArgs( cbMsg.m ) ) ); } return cbMsg; } var getKey = function( msg ) { var m = /^\/(\S+)/.exec( msg ); if (!!m) return m[1]; } var findCommand = function( username, key ) { for (var i = 0; i < commands.length; ++i) { var cmd = commands[i]; if (cmd.key == key && (!cmd.model || username == platform.room_slug)) return cmd; } return null; } var getCommandArgs = function( msg ) { var m = /^\/\S+\s+(.*)/.exec( msg ); if (!m) return []; return m[1].split( /\s+/ ); } init( ); } var main = function( ) { var goal = null; var viewers = {}; var autoStart = platform.settings.auto_start == "Enabled"; var allowMods = platform.settings.allow_mods == "Enabled"; var allowFanclub = platform.settings.allow_fanclub == "Enabled"; var tokensPerMinute = platform.settings.tokens_per_minute; var previewTime = platform.settings.preview_time; var whiteList = util.map( platform.settings.white_list.split( /[ ,;.]+/ ), function( u ) { return u.toLowerCase( ); } ); var lastUpdateTimerTime = util.getTimeSinceEpochInSeconds( ); var totalTips = 0; var commandParser = new CommandParser( ); var init = function( ) { commandParser.register( "start", onStartCommand, true ); commandParser.register( "stop", onStopCommand, true ); commandParser.register( "goal", onGoalCommand, true ); commandParser.register( "reset", onResetCommand, true ); platform.setInterval( onTick, 1000 ); platform.onEnter( cbOnEnter ); platform.onTip( cbOnTip ); platform.onDrawPanel( cbOnDrawPanel ); platform.onMessage( cbOnMessage ); initViewers( ); if (autoStart) start( ); } var onGoalCommand = function( user, amount, optDescription ) { if (!amount || !/\d+/.exec( amount )) platform.notify( platform.room_slug, "Usage: /goal AMOUNT {description}" ); else { // KLUDGE: // Need to reconstruct the description because the command parser splits on whitespace. if (arguments.length > 2) optDescription = Array.prototype.slice.call( arguments, 2 ).join( " " ); amount = parseInt( amount ); if (amount == 0) goal = null; else { if (!goal) goal = new Goal( amount, optDescription ); else goal.update( amount, optDescription ); platform.announce( "Goal has been modified." ); } } } var onResetCommand = function( user ) { goal.received = 0; platform.announce( "Goal reset." ); } var onStartCommand = function( user, optCostPerMinute ) { if (typeof optCostPerMinute != "undefined") tokensPerMinute = parseInt( optCostPerMinute ); if (platform.limitCam_isRunning( )) stop( ); start( ); } var onStopCommand = function( user ) { stop( ); } var stop = function( ) { platform.limitCam_stop( ); platform.announce( "Peep show has paused." ); } var start = function( ) { resetViewerNotifyTimes( ); limitCam( ); platform.announce( "Peep show has started!" ); } var resetViewerNotifyTimes = function( ) { for (name in viewers) viewers[name].lastNotifiedAt = 0; } var limitCam = function( ) { if (!platform.limitCam_isRunning( )) { var msg = "Can't see the show? Hit refresh."; if (tokensPerMinute > 0) msg = "Tip " + tokensPerMinute + " tokens to join the show!"; platform.limitCam_start( msg, getViewerNames( ) ); platform.log( "Starting cam with viewers: " + getViewerNames( ) ); } } var welcomeViewer = function( username ) { if (username != platform.room_slug) { var viewer = getViewer( username ); if (viewer.free) platform.notify( username, "You get to watch for free!" ); else { if (viewer.timeLeft > 0) platform.notify( username, "You have " + util.createReadableDuration( viewer.timeLeft ) + " left." ); if (tokensPerMinute > 0) platform.notify( username, "Tip " + tokensPerMinute + " tokens to add one more minute." ); if (tokensPerMinute > 0 && allowFanclub) platform.notify( username, "Fanclub members get to watch for free!" ); } } } var isFreeUser = function( username ) { var user = platform.getUserByName( username ); if (tokensPerMinute == 0 || (user.in_fanclub && allowFanclub) || (user.is_mod && allowMods)) return true; return cbjs.arrayContains( whiteList, username.toLowerCase( ) ); } var initViewers = function( ) { viewers = {}; for (var i = 0; i < platform.users.length; ++i) { var user = platform.users[i]; tryAddViewer( user.user ); welcomeViewer( user.user ); } } var tryAddViewer = function( username ) { if (username != platform.room_slug && !isViewer( username )) { if (isFreeUser( username )) addFreeViewer( username ); else addViewer( username, previewTime ); return true; } return false; } var addViewer = function( username, time ) { if (!isViewer( username )) { var viewer = new Viewer( username ); viewer.timeLeft = time; viewers[username] = viewer; platform.log( "Added viewer " + username + " with " + time + " seconds." ); } } var addFreeViewer = function( username ) { if (!isViewer( username )) { var viewer = new Viewer( username ); viewer.free = true; viewers[username] = viewer; platform.log( "Added free viewer " + username + "." ); } else { var viewer = getViewer( username ); viewer.free = true; } } var isViewer = function( username ) { return username in viewers; } var getViewer = function( username ) { return viewers[username]; } var removeViewer = function( username ) { delete viewers[username]; } var onTick = function( ) { var t = util.getTimeSinceEpochInSeconds( ); var dt = t - lastUpdateTimerTime; lastUpdateTimerTime = t; if (platform.limitCam_isRunning( )) { limitCam( ); updateViewerTimers( dt ); notifyViewers( ); updateAccessList( ); } platform.drawPanel( ); } var updateViewerTimers = function( dt ) { if (platform.isUserPresent( platform.room_slug )) { for (username in viewers) { var viewer = viewers[username]; if (platform.isUserPresent( username )) { viewer.timeLeft = Math.max( 0, viewer.timeLeft - dt ); viewer.free = isFreeUser( username ); } } } } var notifyViewers = function( ) { if (platform.isUserPresent( platform.room_slug )) { for (username in viewers) { var viewer = viewers[username]; if (platform.isUserPresent( username ) && !viewer.free) { var sinceNotified = viewer.lastNotifiedAt - viewer.timeLeft; if (viewer.lastNotifiedAt == 0 || (viewer.timeLeft <= 30 && viewer.lastNotifiedAt > 30) || (sinceNotified >= 60)) { viewer.lastNotifiedAt = viewer.timeLeft; notifyViewerOfTimeLeft( username, viewer.timeLeft ); } } } } } var notifyViewerOfTimeLeft = function( username, timeLeft ) { platform.notify( username, "You have " + util.createReadableDuration2( Math.ceil( timeLeft ) ) + " left to watch. " + "Tip " + tokensPerMinute + " to add another minute." ); } var updateAccessList = function( ) { var viewerNames = getViewerNames( ); var accessList = platform.limitCam_allUsersWithAccess( ); var usersToRemove = []; var usersToAdd = []; for (var i = 0; i < viewerNames.length; ++i) { var username = viewerNames[i]; if (!cbjs.arrayContains( accessList, username )) usersToAdd.push( username ); } for (var i = 0; i < accessList.length; ++i) { var username = accessList[i]; if (!cbjs.arrayContains( viewerNames, username )) usersToRemove.push( username ); } platform.limitCam_addUsers( usersToAdd ); platform.limitCam_removeUsers( usersToRemove ); if (usersToAdd.length > 0) platform.log( "Added " + usersToAdd.join( ", " ) + " to the access list." ); if (usersToRemove.length > 0) platform.log( "Removed " + usersToRemove.join( ", " ) + " from the access list." ); } var getViewerNames = function( ) { var names = []; for (username in viewers) { var viewer = viewers[username]; if (platform.isUserPresent( viewer.username )) { if (isViewerWatching( viewer )) names.push( viewer.username ); } } return names; } var isWatching = function( username ) { if (username in viewers) return isViewerWatching( viewers[username] ); return false; } var isViewerWatching = function( viewer ) { return viewer.free || viewer.timeLeft > 0; } var cbOnEnter = function( cbUser ) { if (cbUser.user != platform.room_slug) { if (isViewer( cbUser.user )) getViewer( cbUser.user ).free = isFreeUser( cbUser.user ); else tryAddViewer( cbUser.user ) if (platform.limitCam_isRunning( )) welcomeViewer( cbUser.user ); } } var cbOnTip = function( cbTip ) { var tipAmount = parseInt( cbTip.amount ); totalTips += tipAmount; var viewer = getViewer( cbTip.from_user ); var timeAdded = timeFromTip( tipAmount ); viewer.timeLeft = Math.max( 0, viewer.timeLeft ) + timeAdded; viewer.lastNotifiedAt = 0; platform.log( viewer.username + " now has " + Math.ceil( viewer.timeLeft ) + " seconds (+" + timeAdded + ")." ); if (platform.limitCam_isRunning( )) { if (timeAdded > 0) platform.notify( cbTip.from_user, util.createReadableDuration2( timeAdded ) + " have been added." ); } else creditGoal( tipAmount ); platform.notify( platform.room_slug, "You've earned " + totalTips + "tokens in total tips." ); } var creditGoal = function( amount ) { if (goal) { var wasMet = goal.received >= goal.amount; goal.received += amount; if (!wasMet && goal.received >= goal.amount) goalReached( ); else goalAdvanced( ); } } var goalReached = function( ) { platform.announce( "Goal reached!" ); } var goalAdvanced = function( ) { platform.announce( (goal.amount - goal.received) + " tokens left until " + goal.description ); } var timeFromTip = function( amount ) { if (tokensPerMinute > 0) return Math.floor( amount / tokensPerMinute * 60 ); return 0; } var cbOnDrawPanel = function( ) { var rows = []; if (platform.limitCam_isRunning( )) rows.push( createViewersPanelString( ) ); else if (goal) rows.push( createGoalPanelString( ) ); return createPanelFromRows( rows ); } var createPanelFromRows = function( rows ) { var template = { 'template' : "3_rows_11_21_31", 'row1_value' : "", 'row2_value' : "", 'row3_value' : "" }; for (var i = 0; i < Math.min( 3, rows.length ); ++i) template["row"+(i+1)+"_value"] = rows[i]; return template; } var createGoalPanelString = function( ) { return goal.description + " @ " + goal.received + " / " + goal.amount; } var createViewersPanelString = function( ) { return "Viewers: " + getWatcherCount( ); } var getWatcherCount = function( ) { var count = 0; for (username in viewers) if (isViewerWatching( viewers[username] ) && platform.isUserPresent( username )) ++count; return count; } var cbOnMessage = function( cbMsg ) { if (platform.limitCam_isRunning( ) && isWatching( cbMsg.user )) cbMsg.c = "#22CC22"; return cbMsg; } init( ); } var initSettings = function( ) { cb.settings_choices = [ { 'name' : 'allow_fanclub', 'label' : "Free for Fanclub members.", 'type' : 'choice', 'choice1' : "Enabled", 'choice2' : "Disabled" }, { 'name' : 'allow_mods', 'label' : "Free for moderators.", 'type' : 'choice', 'choice1' : "Enabled", 'choice2' : "Disabled" }, { 'name' : 'tokens_per_minute', 'label' : "Tokens per minute.", 'type' : 'int', 'minValue' : 0, 'maxValue' : 999999999, 'defaultValue' : 5 }, { 'name' : 'preview_time', 'label' : "Free preview length (seconds).", 'type' : 'int', 'minValue' : 0, 'maxValue' : 99999999, 'defaultValue' : 60*3 }, { 'name' : 'white_list', 'label' : "Additional free users (separated by space).", 'type' : 'str', 'defaultValue' : "", 'required' : false }, { 'name' : 'auto_start', 'label' : "Auto-start (use \"/start\" command to start manually)", 'type' : 'choice', 'choice1' : "Enabled", 'choice2' : "Disabled" } ]; } new (function( ) { if (Object.keys( cb.settings ).length > 0) main( ); else initSettings( ); })( );
© Copyright Chaturbate 2011- 2024. All Rights Reserved.