Apps Home
|
Create an App
Diamond App - All-in-One
Author:
pricklytree
Description
Source Code
Launch App
Current Users
Created by:
Pricklytree
{ String.prototype.toTitleCase = function() { return this.replace(/\w\S*/g, function(txt) { return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); }); }; // *********************************** Settings control ************************************** const nr_of_welcome_messages = 5; const nr_of_goals = 10; const nr_of_rotating_message = 5; const nr_of_thank_you_messages = 3; const nr_of_tip_menus = 3; const nr_of_tip_menus_lines = 10; const nr_of_lovense_levels = 6; const nr_of_lovense_specials = 3; // *********************************** Defaults ************************************** const default_settings = { 'welcome_message_1_enable' : 'Yes', 'welcome_message_1_message': 'Hi {username}!{newline}So happy you are here! {icon:teddy}{newline}{newline}{icon:diamond} Type /tips to see the Tip Menu{newline}:lushsm Type /lush to see the Lovense Lush Levels{newline}:KrystalSmith_1{newline}{icon:kiss}{icon:kiss}{icon:kiss} Your Krystal', 'welcome_message_1_style' : 'Rainbow Light', 'welcome_message_1_icon' : '- None -', 'rotating_message_1_enable' : 'Yes', 'rotating_message_1_message' : 'Type /tips to see the Tip Menu{OR}Type /lush to see the Lovense Lush Levels', 'rotating_message_1_style' : 'Blue Light', 'rotating_message_1_icon' : 'point', 'rotating_message_1_interval': 240, 'rotating_message_2_enable' : 'Yes', 'rotating_message_2_message' : ':KrystalSmith_1', 'rotating_message_2_style' : '- None -', 'rotating_message_2_icon' : '- None -', 'rotating_message_2_interval': 240, 'rotating_message_2_offset' : 120, 'rotating_message_3_enable' : 'Yes', 'rotating_message_3_message' : ':pinkfollooww', 'rotating_message_3_style' : '- None -', 'rotating_message_3_icon' : '- None -', 'rotating_message_3_interval': 600, 'thank_you_message_1_enable' : 'Yes', 'thank_you_message_1_message' : '{username} tipped for: {tip_text}', 'thank_you_message_1_in_tip_menus' : 'Yes', 'thank_you_message_1_min_amount' : 9, 'thank_you_message_1_style' : 'Blue Light', 'thank_you_message_1_icon' : 'Kiss', 'thank_you_message_1_send_to_group': 'Everyone', 'thank_you_message_2_enable' : 'Yes', 'thank_you_message_2_message' : 'My Lovense Lush has been activated by {username} for: {lush_text} ({lush_duration})', 'thank_you_message_2_in_tip_menus' : 'Optional', 'thank_you_message_2_min_amount' : 3, 'thank_you_message_2_style' : 'Pink Light', 'thank_you_message_2_icon' : 'Lush Animated', 'thank_you_message_2_send_to_group': 'Everyone', 'thank_you_message_3_enable' : 'Yes', 'thank_you_message_3_message' : '{icon:Random Thank You}', 'thank_you_message_3_in_tip_menus' : 'Optional', 'thank_you_message_3_min_amount' : 3, 'thank_you_message_3_style' : '- None -', 'thank_you_message_3_icon' : '- None -', 'thank_you_message_3_send_to_group': 'Everyone', 'no_tips_message_enable' : 'Yes', 'no_tips_message_message' : ':notips23', 'no_tips_message_start' : 600, 'no_tips_message_interval': 600, 'no_tips_message_style' : '- None -', 'no_tips_message_icon' : '- None -', 'tips_menu_1_enter' : 'Yes', 'tips_menu_1_enter_delay' : 20, 'tips_menu_1_enable' : 'Yes', 'tips_menu_1_interval' : 900, 'tips_menu_1_title_icons' : 'Yes', 'tips_menu_1_footer' : '{icon:point} Type /tips to see this Tip Menu', 'tips_menu_1_footer_separator': 'Icons', 'tips_menu_1_icon_line_length': 40, 'tips_menu_1_group_separator' : 'Newline', 'tips_menu_1_price_separator' : 'Colon', 'tips_menu_1_line_1' : '9 Air kiss; 11 "I love you, Krystal"', 'tips_menu_1_line_2' : '22 Suck finger; 33 Show eyes up close; 44 Show feet; 55 Flash boobs; 66 Suck dildo', 'tips_menu_1_line_3' : '77 Show ass (3min); 88 {hideinmenu}Show ass (3min) {/hideinmenu}+ Your choice: Stroking / Spanking / Oil', 'tips_menu_1_line_4' : '111 Show boobs (3min); 122 {hideinmenu}Show boobs (3min) {/hideinmenu}+ Your choice: Stroking / Playing / Licking / Oil', 'tips_menu_1_line_5' : '222 Show pussy (3min); 244 {hideinmenu}Show pussy (3min) {/hideinmenu}+ Your choice: Fingering / Dildo / Oil / Domi', 'tips_menu_1_line_6' : '333 Fully naked (5min); 366 {hideinmenu}Fully naked (5min) {/hideinmenu}+ Your choice: Playing / Dildo / Anal plug / Oil / Domi', 'tips_menu_1_line_7' : '666 Control my lovense (3min); 888 Control my lovense (5min)', 'tips_menu_1_line_8' : '1111 Krystal, buy something for yourself', 'tips_menu_2_enter' : 'No', 'tips_menu_2_enable' : 'Yes', 'tips_menu_2_interval' : 300, 'tips_menu_2_skip_main' : 240, 'tips_menu_2_title_icons' : 'Yes', 'tips_menu_2_footer' : '{icon:point} Type /tips to see the full Tip Menu', 'tips_menu_2_footer_separator': 'Icons', 'tips_menu_2_icon_line_length': 40, 'tips_menu_2_group_separator' : '- None -', 'tips_menu_2_price_separator' : 'Colon', 'tips_menu_2_line_1' : '11 "I love you, Krystal"', 'tips_menu_2_line_2' : '33 Show eyes up close', 'tips_menu_2_line_3' : '55 Flash boobs', 'tips_menu_2_line_4' : '77 Show ass (3min)', 'tips_menu_2_line_5' : '111 Show boobs (3min)', 'tips_menu_2_line_6' : '222 Show pussy (3min)', 'tips_menu_2_line_7' : '333 Fully naked (5min)', 'tips_menu_2_line_8' : '1111 Krystal, buy something for yourself', 'lovense_style' : '- Random Light -', 'lovense_icon_style' : 'Lovense Lush Style 1', 'lovense_footer_separator': 'Icons', 'lovense_footer' : '{icon:point} Type /lush to see these Lovense Lush Levels', 'lovense_enter' : 'Yes', 'lovense_enter_delay' : 10, 'lovense_auto' : 'Yes', 'lovense_interval' : 540, 'lovense_levels_title' : '', 'lovense_levels_icon' : 'Star', 'lovense_levels_title_icons' : 'Yes', 'lovense_levels_price_separator': 'Lush Icon', 'lovense_level_1_level' : 'Low', 'lovense_level_1_price_from' : 3, 'lovense_level_1_price_to' : 9, 'lovense_level_1_duration' : 3, 'lovense_level_2_level' : 'Low', 'lovense_level_2_price_from' : 10, 'lovense_level_2_price_to' : 49, 'lovense_level_2_duration' : 15, 'lovense_level_3_level' : 'Medium', 'lovense_level_3_price_from' : 50, 'lovense_level_3_price_to' : 99, 'lovense_level_3_duration' : 30, 'lovense_level_4_level' : 'High', 'lovense_level_4_price_from' : 100, 'lovense_level_4_price_to' : 199, 'lovense_level_4_duration' : 45, 'lovense_level_5_level' : 'Ultra High', 'lovense_level_5_price_from' : 200, 'lovense_level_5_price_to' : 0, 'lovense_level_5_duration' : 60, 'lovense_level_6_enable' : 'No', 'lovense_patterns_title' : '', 'lovense_patterns_icon' : 'Star', 'lovense_patterns_title_icons' : 'Yes', 'lovense_patterns_price_separator' : 'Lush Icon', 'lovense_pattern_random_enable' : 'No', 'lovense_pattern_pulse_price' : 251, 'lovense_pattern_pulse_duration' : 60, 'lovense_pattern_wave_price' : 252, 'lovense_pattern_wave_duration' : 60, 'lovense_pattern_fireworks_price' : 253, 'lovense_pattern_fireworks_duration' : 60, 'lovense_pattern_earthquake_price' : 254, 'lovense_pattern_earthquake_duration': 60, 'lovense_specials_title' : '', 'lovense_specials_icon' : 'Star', 'lovense_specials_title_icons' : 'Yes', 'lovense_specials_price_separator': 'Lush Icon', 'lovense_special_1_enable' : 'Yes', 'lovense_special_1_description' : 'Control my Lush', 'lovense_special_1_price' : 444, 'lovense_special_1_duration' : 120, 'lovense_special_1_icon' : 'Diamond', 'lovense_special_1_style' : 'Purple', 'lovense_special_1_message' : 'Thank you so much. Please use the link I will send to you in a PM to control my Lovense Lush {icon:kiss-wink}', 'lovense_special_1_send_to_group': 'Tipper & Room Owner & Moderators', 'lovense_special_2_enable' : 'Yes', 'lovense_special_2_description' : 'Control my Lush', 'lovense_special_2_price' : 666, 'lovense_special_2_duration' : 240, 'lovense_special_2_icon' : 'Diamond', 'lovense_special_2_style' : 'Purple', 'lovense_special_2_message' : 'Thank you so much. Please use the link I will send to you in a PM to control my Lovense Lush {icon:kiss-wink}', 'lovense_special_2_send_to_group': 'Tipper & Room Owner & Moderators', }; // *********************************** Variables ************************************** let message_queue = []; let message_queue_running = false; let settings_notice_count = 0; let section_letter = 64; let start_time = Date.now(); let now = 0; let last_tip_time = 0; let total_tipped = 0; let all_tips = []; let tip_totals = {}; let best_tippers = []; let best_tippers_usernames = []; let highest_tip = {'username': '', 'amount': 0}; let latest_tip = {'username': '', 'amount': 0}; let goals = []; let last_main_tip_menu_shown = 0; let tip_items = { tip_menu_items: [], lovense_items : [] }; let random_thank_you_icon_number = 10; let user_groups = {}; let random = {}; let room_users = []; let user_objects = []; let styles = {}; let colors = {}; let icons = {}; let lovense_icon_styles = {}; const lovense_patterns = [ 'random', 'pulse', 'wave', 'fireworks', 'earthquake' ]; // *********************************** Events ************************************** cb.onStart(user => { // empty message queue message_queue = []; initVars(); updateUsersList(user); initGoals(); initTips(); initMessageQueue(); }); cb.onEnter(function(user) { updateUsersList(user); addWelcomeMessagesToQueue(user); addTipMenusOnEnterToQueue(user); addLovenseLevelsOnEnterToQueue(user); initMessageQueue(); }); cb.onLeave(function(user) { updateUsersList(user); }); cb.onFollow(function(user) { showNewFollowerMessage(user); }); cb.onTip(function(tip_data) { handleTip(tip_data); }); cb.onMessage(function(msg) { return handleMessage(msg); }); handleTip = function(tip_data) { updateTipData(tip_data); showGoalMessage(tip_data); showThankYouMessages(tip_data); last_tip_time = now; }; handleMessage = function(msg) { if (handleCommands(msg)) { log(msg); return msg; } let prefix; if (userPassesGroup(msg.user, 'owner')) { prefix = cb.settings['message_prefixes_owner']; } else if (userPassesGroup(msg.user, 'moderator')) { prefix = cb.settings['message_prefixes_moderator']; } else { prefix = cb.settings['message_prefixes_user']; } log(msg.user); log(getUserByName(msg.user)); prefix = prefix.replace( /{tipped}/, typeof tip_totals[msg.user] !== 'undefined' ? tip_totals[msg.user] : 0 ); prefix = prepareMessage(prefix, msg.user); msg.m = (prefix + ' ' + msg.m).trim(); return msg; }; handleCommands = function(msg) { switch (msg.m) { case '/tips': case '/menu': case '/tipmenu': case '/tp': cb.setTimeout(() => { showTipMenu(1, msg.user); }, 100); styleMessageAsCommand(msg); return true; case '/lush': case '/lovense': case '/levels': cb.setTimeout(() => { showLovenseLevels(msg.user); }, 100); styleMessageAsCommand(msg); return true; } return handleModeratorCommands(msg); }; handleModeratorCommands = function(msg) { if (!userPassesGroup(msg.user, 'owner_mods')) { return false; } switch (msg.m) { case '/stats': cb.getRoomOwnerData(ownerData => { if (!ownerData['success']) { return; } const nl = '\n. . . . . . . . . . . . . . . . . . '; const stats = [ ':::: STATISTICS ::::', 'Time Online: ' + nl + getTimeOnline(), 'Number of Followers: ' + nl + ownerData['data']['followers'], '', ':::: GOAL DATA ::::', 'Number of Goals Reached: ' + nl + getTotalGoalsReached(), '', ':::: TIP DATA ::::', 'Total Tipped: ' + nl + total_tipped, ]; if (best_tippers.length) { stats.push( 'Total Number of Tips: ' + nl + all_tips.length, 'Total Number of Tippers: ' + nl + Object.keys(tip_totals).length, 'Highest Tip: ' + nl + highest_tip.amount + ' (' + highest_tip.username + ')', '', ':::: TIPPERS ::::' ); for (let i in best_tippers) { stats.push( ' #' + (parseInt(i) + 1) + ' [' + pad(best_tippers[i].amount, 0, best_tippers[0].amount.toString().length) + ']' + ' ' + best_tippers[i].username ); } } cb.setTimeout(() => { log(stats.join('\n'), msg.user); }, 100); }); styleMessageAsCommand(msg); return true; case '/dev_new_follower': cb.setTimeout(() => { log('Simulating: New follower: ' + msg.user); showNewFollowerMessage(msg.user); }, 100); styleMessageAsCommand(msg); return true; case '/dev_tip': cb.setTimeout(() => { simulateTip(msg.user, Math.floor(Math.random() * (301)) + 1); }, 100); styleMessageAsCommand(msg); return true; case '/dev_tip_random': cb.setTimeout(() => { simulateRandomUserTip(Math.floor(Math.random() * (301)) + 1); }, 100); styleMessageAsCommand(msg); return true; } let msg_match = msg.m.match(/^\/dev_tip_([0-9]+)$/); if (msg_match) { cb.setTimeout(() => { simulateTip(msg.user, msg_match[1]); }, 100); styleMessageAsCommand(msg); return true; } msg_match = msg.m.match(/^\/dev_tip_random_([0-9]+)$/); if (msg_match) { cb.setTimeout(() => { for (i = 0; i < msg_match[1]; i++) { simulateRandomUserTip(Math.floor(Math.random() * (301)) + 1); } }, 100); styleMessageAsCommand(msg); return true; } return false; }; simulateTip = function(user_name, amount) { const user = getUserByName(user_name); if (user === null) { return; } const tip_data = { 'amount' : amount, 'from_user' : user.user, 'is_anon_tip': false, }; log('Simulating: ' + tip_data.from_user + ' tipped ' + tip_data.amount + ' tokens'); handleTip(tip_data); }; simulateRandomUserTip = function(amount) { const tip_data = { 'amount' : amount, 'from_user' : getRandomMessagePart([ 'brunobanana', 'joystickle', 'creampieter', 'proposition69', 'lonelyolddude', '1wants2tip4u', 'dickvandike', 'titillating' ].join('{OR}')), 'is_anon_tip': false, }; log('Simulating: ' + tip_data.from_user + ' tipped ' + tip_data.amount + ' tokens'); handleTip(tip_data); }; styleMessageAsCommand = function(msg) { msg.c = '#999999'; msg.background = '#eeeeee'; msg['X-Spam'] = true; }; // *********************************** Functions ************************************** init = function() { initVars(); initSettings(); }; initVars = function() { /* in_fanclub: is the user in the broadcasters fan club has_tokens: does the user have at least 1 token is_mod: is the user a moderator tipped_recently: is the user a “dark blue”? tipped_alot_recently: is the user a “purple”? tipped_tons_recently: is the user a “dark purple”? */ user_groups = { '0' : 'Everyone', 'grey' : 'Has NO tokens', 'lightblue' : 'Owns or has purchased tokens', 'darkblue' : 'Tipped at least 50 tokens in the past 2 weeks', 'lightpurple': 'Tipped at least 250 tokens in the past 2 weeks', 'darkpurple' : 'Tipped at least 1000 tokens in the past 2 weeks', 'green' : 'Fan club members', 'moderator' : 'Moderators', 'room_owner' : 'Room Owner', 'owner_mods' : 'Room Owner & Moderators' }; colors = { 'black' : '#000000', 'gray' : '#4f5a6c', 'red' : '#b02120', 'orange': '#c85510', 'yellow': '#cc860f', 'green' : '#138038', 'teal' : '#0c7b83', 'blue' : '#0d4aae', 'purple': '#5e15ae', 'pink' : '#a81483' }; styles = { 'Rainbow' : { 'background': 'linear-gradient(63.435deg, rgb(220, 42, 40), rgb(255, 168, 19), rgb(255, 168, 19), rgb(24, 160, 71), rgb(17, 93, 218), rgb(118, 27, 218), rgb(211, 25, 164), rgb(220, 42, 40))', 'color' : '#ffffff' }, 'Rainbow Light': { 'background': 'linear-gradient(63.435deg, rgba(220, 42, 40, 0.20), rgba(255, 168, 19, 0.20), rgba(255, 168, 19, 0.20), rgba(24, 160, 71, 0.20), rgba(17, 93, 218, 0.20), rgba(118, 27, 218, 0.20), rgba(211, 25, 164, 0.20), rgba(220, 42, 40, 0.20))', 'color' : '#000000' }, 'Red' : { 'background': getBackgroundColorDark('220, 42, 40'), 'color' : '#fcf0ef' }, 'Red Light' : { 'background': getBackgroundColorLight('220, 42, 40'), 'color' : '#5e1211' }, 'Orange' : { 'background': getBackgroundColorDark('251, 107, 20'), 'color' : '#fef4ee' }, 'Orange Light' : { 'background': getBackgroundColorLight('251, 107, 20'), 'color' : '#6b2e08' }, 'Yellow' : { 'background': getBackgroundColorDark('255, 168, 19'), 'color' : '#fff8ee' }, 'Yellow Light' : { 'background': getBackgroundColorLight('255, 168, 19'), 'color' : '#6d4808' }, 'Green' : { 'background': getBackgroundColorDark('24, 160, 71'), 'color' : '#eef8f2' }, 'Green Light' : { 'background': getBackgroundColorLight('24, 160, 71'), 'color' : '#0a441e' }, 'Teal' : { 'background': getBackgroundColorDark('15, 154, 164'), 'color' : '#eef7f8' }, 'Teal Light' : { 'background': getBackgroundColorLight('15, 154, 164'), 'color' : '#064246' }, 'Blue' : { 'background': getBackgroundColorDark('17, 93, 218'), 'color' : '#eef3fc' }, 'Blue Light' : { 'background': getBackgroundColorLight('17, 93, 218'), 'color' : '#07275d' }, 'Purple' : { 'background': getBackgroundColorDark('118, 27, 218'), 'color' : '#f5effc' }, 'Purple Light' : { 'background': getBackgroundColorLight('118, 27, 218'), 'color' : '#320b5d' }, 'Pink' : { 'background': getBackgroundColorDark('211, 25, 164'), 'color' : '#fbeef8' }, 'Pink Light' : { 'background': getBackgroundColorLight('211, 25, 164'), 'color' : '#5a0a46' }, 'Gray' : { 'background': getBackgroundColorDark('99, 113, 136'), 'color' : '#f4f5f6' }, 'Gray Light' : { 'background': getBackgroundColorLight('99, 113, 136'), 'color' : '#2a303a' } }; icons = { 'diamond' : String.fromCodePoint(0x0001F48E), // 💎, 'heart' : String.fromCodePoint(0x0001F496), // 💖, 'hearts' : String.fromCodePoint(0x0001F49E), // 💞, 'kiss' : String.fromCodePoint(0x0001F48B), // 💋️, 'kiss-wink' : String.fromCodePoint(0x0001F618), // 😘, 'in love' : String.fromCodePoint(0x0001F970), // 🥰, 'love eyes' : String.fromCodePoint(0x0001F60D), // 😍, 'love cat' : String.fromCodePoint(0x0001F63B), // 😻, 'teddy' : String.fromCodePoint(0x0001F9F8), // 🧸, 'ribbon' : String.fromCodePoint(0x0001F380), // 🎀, 'balloon' : String.fromCodePoint(0x0001F388), // 🎈, 'crown' : String.fromCodePoint(0x0001F451), // 👑, 'cup' : String.fromCodePoint(0x0001F3C6), // 👑, 'party' : String.fromCodePoint(0x0001F973), // 🥳, 'rose' : String.fromCodePoint(0x0001F339), // 🌹️, 'flower 1' : String.fromCodePoint(0x0001F33A), // 🌺, 'flower 2' : String.fromCodePoint(0x0001F338), // 🌸, 'flower 3' : String.fromCodePoint(0x0001F33C), // 🌼, 'star' : String.fromCodePoint(0x00002B50), // ⭐, 'stars' : String.fromCodePoint(0x00002728), // ✨, 'alarm' : String.fromCodePoint(0x0001F6A8), // 🚨, 'fire' : String.fromCodePoint(0x0001F525), // 🔥, 'point' : String.fromCodePoint(0x0001F449), // 👉, 'thumbs up' : String.fromCodePoint(0x0001F44D), // 👍, 'heart orange' : String.fromCodePoint(0x0001F9E1), // 🧡, 'heart yellow' : String.fromCodePoint(0x0001F49B), // 💛, 'heart green' : String.fromCodePoint(0x0001F49A), // 💚, 'heart blue' : String.fromCodePoint(0x0001F499), // 💙, 'heart purple' : String.fromCodePoint(0x0001F49C), // 💜, 'heart black' : String.fromCodePoint(0x0001F5A4), // 🖤, 'heart white' : String.fromCodePoint(0x0001F90D), // 🤍, 'lush' : ':lushsm', 'lush 2' : ':wm_toy_lush', 'lush animated': ':wm_toy_lush_active', }; lovense_icon_styles = { 'Lovense Lush Style 1': { '1' : ':llvlc1', '2' : ':llvlc2', '3' : ':llvlc3', '4' : ':llvlc4', '5' : ':llvlc5', '6' : ':llvlc6', 'random' : ':lslvl1', 'pulse' : ':lslvl2', 'wave' : ':lslvl3', 'fireworks' : ':lslvl4', 'earthquake': ':lslvl5', }, 'Lovense Lush Style 2': { '1' : ':ldreamlev1lo', '2' : ':ldreamlev2lo', '3' : ':ldreamlev3me', '4' : ':ldreamlev4hi', '5' : ':ldreamlev5hi', '6' : ':ldreamlev6hi', 'random' : ':ldreamrandom', 'pulse' : ':ldreampulse', 'wave' : ':ldreamwave', 'fireworks' : ':ldreamfireworks', 'earthquake': ':ldreamearth' }, 'Lovense Lush Style 3': { '1' : ':lflvl1', '2' : ':lflvl2', '3' : ':lflvl3', '4' : ':lflvl4', '5' : ':lflvl5', '6' : ':lflvl6', 'random' : ':lfrandom1', 'pulse' : ':lfpulse1', 'wave' : ':lfwave1', 'fireworks' : ':lffireworks1', 'earthquake': ':lfearth1' }, }; }; initMessageQueue = function() { if (message_queue_running) { return; } message_queue_running = true; addLeaderBoardToQueue(); addRotatingMessagesToQueue(); addSingleTipsToQueue(); addTipMenusToQueue(); addLovenseLevelsToQueue(); cb.setTimeout(handleMessageQueue, 1000); }; initSettings = function() { cb.settings_choices = [].concat( getSettingsTOC(), getSettingsPanel(), getSettingsGoals(), getSettingsLeaderBoard(), getSettingsMessagePrefixes(), getSettingsWelcomeMessages(), getSettingsRotatingMessages(), getSettingsNewFollowerMessages(), getSettingsThankYouMessages(), getSettingsNoTipsMessages(), getSettingsSingleTips(), getSettingsTipMenus(), getSettingsLovenseLevels() ); for (let i in cb.settings_choices) { let key = cb.settings_choices[i].name; if (typeof default_settings[key] === 'undefined') { continue; } cb.settings_choices[i].defaultValue = default_settings[key]; } }; initGoals = function() { for (let num = 1; num <= nr_of_goals; num++) { let goal = cb.settings['goal_' + num]; if (!goal) { continue; } goals.push(goal); } }; initTips = function() { initTipMenuItems(); initLovenseItems(); }; initTipMenuItems = function() { for (let num = 1; num <= nr_of_tip_menus; num++) { const prefix = 'tips_menu_' + num + '_'; if (cb.settings[prefix + 'enable'] !== 'Yes') { continue; } for (let line_num = 1; line_num <= nr_of_tip_menus_lines; line_num++) { let line = cb.settings[prefix + 'line_' + line_num]; if (!line) { continue; } const tips = getTipLinesFromString(line); if (!tips) { continue; } for (let tip of tips) { if (typeof tip_items.tip_menu_items[tip.price] !== 'undefined') { continue; } tip_items.tip_menu_items[tip.price] = tip; } } } tip_items.tip_menu_items = tip_items.tip_menu_items.filter(function(item) { return typeof item !== 'undefined'; }); }; initLovenseItems = function() { for (let num = 1; num <= nr_of_lovense_levels; num++) { const prefix = 'lovense_level_' + num + '_'; if (cb.settings[prefix + 'enable'] !== 'Yes') { continue; } const price_from = cb.settings[prefix + 'price_from']; const price_to = cb.settings[prefix + 'price_to']; const price = price_from + (price_to ? '-' + price_to : '+'); tip_items.lovense_items.push({ 'text' : 'Lovense Lush ' + cb.settings[prefix + 'level'].toTitleCase() + ' (' + getDuration(prefix + 'duration') + ')', 'price': price, }); } for (let pattern of lovense_patterns) { const prefix = 'lovense_pattern_' + pattern + '_'; if (cb.settings[prefix + 'enable'] !== 'Yes') { continue; } const item_price = cb.settings[prefix + 'price']; tip_items.lovense_items.push({ 'text' : 'Lovense Lush ' + pattern.toTitleCase() + ' (' + getDuration(prefix + 'duration') + ')', 'price': item_price, }); } for (let num = 1; num <= nr_of_lovense_specials; num++) { const prefix = 'lovense_special_' + num + '_'; if (cb.settings[prefix + 'enable'] !== 'Yes') { continue; } const item_price = cb.settings[prefix + 'price']; tip_items.lovense_items.push({ 'text' : getText(prefix + 'description') + ' (' + getDuration(prefix + 'duration') + ')', 'price': item_price, }); } }; getSettingsTOC = function() { let settings = [form.title('Table of Contents')]; resetSectionLetter(); settings.push(form.createTitle('[' + getNextSectionLetter() + '] Panel Settings')); settings.push(form.createTitle('[' + getNextSectionLetter() + '] Goals')); settings.push(form.createTitle('[' + getNextSectionLetter() + '] Leader Board')); settings.push(form.createTitle('[' + getNextSectionLetter() + '] Message Prefixes')); settings.push(form.createTitle('[' + getNextSectionLetter() + '] Welcome Messages')); settings.push(form.createTitle('[' + getNextSectionLetter() + '] Rotating Messages')); settings.push(form.createTitle('[' + getNextSectionLetter() + '] New Follower Messages')); settings.push(form.createTitle('[' + getNextSectionLetter() + '] Tip Thank You Messages')); settings.push(form.createTitle('[' + getNextSectionLetter() + '] No Tips Messages')); settings.push(form.createTitle('[' + getNextSectionLetter() + '] Random Single Tip Messages')); settings.push(form.createTitle('[' + getNextSectionLetter() + '] Tip Menu\'s')); settings.push(form.createTitle('[' + getNextSectionLetter() + '] Lovense Lush Levels')); settings.push(form.line()); resetSectionLetter(); return settings; }; getSettingsPanel = function() { const letter = getNextSectionLetter(); const prefix = 'panel_settings_'; return [ form.title('[' + letter + '] Panel Settings'), { name : prefix + 'show_goals', label : 'Show Goals', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'Yes', required : false }, { name : prefix + 'show_totals', label : 'Show Best/Highest/Latest', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'Yes', required : false }, { name : prefix + 'show_leader_board', label : 'Show Leader Board', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'Yes', required : false }, { name : prefix + 'timeout', label : 'Seconds per panel', type : 'int', defaultValue: 4, minValue : 1, maxValue : 60, required : false }, form.subSubTitle('Icons'), form.icons(prefix + 'icon_goal', 'Goal', 'Fire'), form.icons(prefix + 'icon_progress_empty', 'Progress Bar Empty', 'Heart White'), form.icons(prefix + 'icon_progress_completed', 'Progress Bar Filled', 'Heart Purple'), { name : prefix + 'icon_progress_multicolor', label : 'Use Multicolor hearts on 100%', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'Yes', required : false }, form.icons(prefix + 'icon_remaining', 'Remaining', 'Point'), form.line(2, 10), form.icons(prefix + 'icon_best_tipper', 'Best Tipper', 'Diamond'), form.icons(prefix + 'icon_highest_tip', 'Highest Tip', 'Star'), form.icons(prefix + 'icon_latest_tip', 'Latest Tip', 'Kiss'), form.line(2, 10), form.icons(prefix + 'icon_leader_board_1', 'Leader Board #1', 'Diamond'), form.icons(prefix + 'icon_leader_board_2', '#2', 'Star'), form.icons(prefix + 'icon_leader_board_3', '#3', 'Kiss'), form.subSubTitle('Text Colors'), form.colors(prefix + 'color_title_1', 'Top Row: Title', 'Purple'), form.colors(prefix + 'color_text_1', 'Value', 'Black'), form.line(2, 10), form.colors(prefix + 'color_title_2', 'Middle Row: Title', 'Green'), form.colors(prefix + 'color_text_2', 'Value', 'Black'), form.line(2, 10), form.colors(prefix + 'color_title_3', 'Bottom Row: Title', 'Blue'), form.colors(prefix + 'color_text_3', 'Value', 'Black'), ]; }; getSettingsGoals = function() { const letter = getNextSectionLetter(); let prefix = 'goals_'; let settings = [ form.title('[' + letter + '] Goals'), { name : prefix + 'amount', label : 'Token Amount Per Goal', type : 'int', defaultValue: 500, minValue : 1, maxValue : 99999999, required : false } ]; for (let num = 1; num <= nr_of_goals; num++) { settings.push( { name : 'goal_' + num, label : 'Goal ' + num, type : 'str', required: false } ); } prefix = 'goals_message_on_reached_'; settings.push( form.subSubTitle('Message On Goal Reached'), { name : prefix + 'enable', label : 'Message On Goal Reached', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'Yes', required : false }, form.notice('{tipped}, {goal}, {goal_amount}, {goal_remaining}', 'Available Dynamic Tags'), form.notice('{username}, {icon}, {newline}, {OR}', 'Available Dynamic Tags'), { name : prefix + 'message', label : 'Message', type : 'str', defaultValue: '{icon:party} We reached the goal: {goal}!{newline}{icon:thumbs up} Thank you {username} and the other tippers!', required : false }, form.styles(prefix + 'style', null, 'Green'), form.icons(prefix + 'icon', null, '- None -'), form.userGroups(prefix + 'send_to_group') ); prefix = 'goals_message_on_update_'; settings.push( form.subSubTitle('Message On Tips'), { name : prefix + 'enable', label : 'Message On Tips', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'No', required : false }, form.notice('{tipped}, {goal}, {goal_amount}, {goal_remaining}', 'Available Dynamic Tags'), form.notice('{username}, {icon}, {newline}, {OR}', 'Available Dynamic Tags'), { name : prefix + 'message', label : 'Message', type : 'str', defaultValue: '{icon:party} Just {goal_remaining} tokens remaining to reach the goal: {goal}!{newline}{icon:thumbs up} Thank you {username}!', required : false }, { name : prefix + 'min_amount', label : 'Minimum Tip Value', type : 'int', defaultValue: 10, minValue : 1, maxValue : 99999999, required : false }, form.styles(prefix + 'style', null, 'Green Light'), form.icons(prefix + 'icon', null, '- None -'), form.userGroupsPlusSelf(prefix + 'send_to_group', 'Tipper', 'Send Message to', 'Everyone') ); return settings; }; getSettingsLeaderBoard = function() { const letter = getNextSectionLetter(); const prefix = 'leader_board_'; return [ form.title('[' + letter + '] Leader Board'), { name : prefix + 'min', label : 'Minimum Number of Leaders', type : 'int', defaultValue: 2, minValue : 1, maxValue : 3, required : false }, { name : prefix + 'max', label : 'Maximum Number of Leaders', type : 'int', defaultValue: 3, minValue : 3, maxValue : 10, required : false }, form.styles(prefix + 'style', null, 'Gray Light'), form.icons(prefix + 'icon', null, 'Crown'), { name : prefix + 'title', label : 'Title', type : 'str', required: false }, { name : prefix + 'title_icons', label : 'Title Icons', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'Yes', required : false }, { name : prefix + 'footer', label : 'Footer', type : 'str', required: false }, { name : prefix + 'footer_separator', label : 'Footer Separator', type : 'choice', choice1 : '- None -', choice2 : 'Newline', choice3 : 'Icons', defaultValue: 'Icons', required : false }, { name : prefix + 'icon_line_length', label : 'Icon Line Length', type : 'int', defaultValue: 40, minValue : 10, maxValue : 100, required : false }, form.userGroups(prefix + 'send_to_group'), form.subSubTitle('Post on Leader Changes'), { name : prefix + 'post_on_change', label : 'Post on Leader Changes', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'Yes', required : false }, form.subSubTitle('Auto Post'), { name : prefix + 'auto', label : 'Auto Post', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'Yes', required : false }, { name : prefix + 'interval', label : 'Interval (secs)', type : 'int', defaultValue: 600, minValue : 1, maxValue : 1200, required : false }, { name : prefix + 'interval_offset', label : 'Offset (secs)', type : 'int', defaultValue: 90, minValue : 0, maxValue : 1200, required : false } ]; }; getSettingsMessagePrefixes = function() { const letter = getNextSectionLetter(); const prefix = 'message_prefixes_'; return [ form.title('[' + letter + '] Message Prefixes'), form.notice('{tipped}, {newline}', 'Available Dynamic Tags'), { name : prefix + 'owner', label : 'Owner Prefix', type : 'str', defaultValue: ':icon_crown :', required : false }, { name : prefix + 'moderator', label : 'Moderator Prefix', type : 'str', defaultValue: ':dbmod28 :', required : false }, { name : prefix + 'user', label : 'Other Users Prefix', type : 'str', defaultValue: '[{tipped}] :', required : false } ]; }; getSettingsWelcomeMessages = function() { const letter = getNextSectionLetter(); let settings = [ form.title('[' + letter + '] Welcome Messages'), form.notice('{username}, {icon}, {newline}', 'Available Dynamic Tags') ]; for (let num = 1; num <= nr_of_welcome_messages; num++) { const prefix = 'welcome_message_' + num + '_'; settings.push( form.subTitle('[' + letter + '.' + num + '] Welcome Message ' + num), { name : prefix + 'enable', label : 'Enable', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'No', required : false }, { name : prefix + 'message', label : 'Message', type : 'str', required: false }, form.styles(prefix + 'style'), form.icons(prefix + 'icon'), form.userGroups(prefix + 'user_level', 'User Level of Visitor'), form.userGroupsPlusSelf(prefix + 'send_to_group', 'Visitor', 'Send Message to'), { name : prefix + 'delay', label : 'Delay (secs)', type : 'int', defaultValue: 0, minValue : 0, maxValue : 1200, required : false } ); } return settings; }; getSettingsRotatingMessages = function() { const letter = getNextSectionLetter(); let settings = [ form.title('[' + letter + '] Rotating Messages'), form.notice('{icon}, {newline}, {OR}', 'Available Dynamic Tags') ]; for (let num = 1; num <= nr_of_rotating_message; num++) { const prefix = 'rotating_message_' + num + '_'; settings.push( form.subTitle('[' + letter + '.' + num + '] Rotating Message ' + num), { name : prefix + 'enable', label : 'Enable', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'No', required : false }, { name : prefix + 'message', label : 'Message', type : 'str', required: false }, form.styles(prefix + 'style'), form.icons(prefix + 'icon'), form.userGroups(prefix + 'send_to_group'), { name : prefix + 'interval', label : 'Interval (secs)', type : 'int', defaultValue: 300, minValue : 1, maxValue : 1200, required : false }, { name : prefix + 'interval_offset', label : 'Offset (secs)', type : 'int', defaultValue: 0, minValue : 0, maxValue : 1200, required : false } ); } return settings; }; getSettingsNewFollowerMessages = function() { const letter = getNextSectionLetter(); const prefix = 'new_follower_messages_'; return [ form.title('[' + letter + '] New Follower Messages'), { name : prefix + 'enable', label : 'Enable', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'Yes', required : false }, form.notice('{username}, {icon}, {newline}, {OR}', 'Available Dynamic Tags'), { name : prefix + 'message', label : 'Message', type : 'str', defaultValue: 'Thanks for following me, {username}! {icon:kisswink}', required : false }, form.styles(prefix + 'style', null, 'Orange'), form.icons(prefix + 'icon', null, '- None -'), form.userGroups(prefix + 'user_level', 'User Level of Visitor'), form.userGroupsPlusSelf(prefix + 'send_to_group', 'Follower', '', 'Everyone') ]; }; getSettingsThankYouMessages = function() { const letter = getNextSectionLetter(); const prefix = 'thank_you_messages_'; let settings = [ form.title('[' + letter + '] Tip Thank You Messages'), { name : prefix + 'include_anonymous', label : 'Include Anonymous Tippers', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'Yes', required : false }, { name : prefix + 'anonymous_name', label : 'Message', type : 'str', defaultValue: 'an anonymous user', required : false }, form.notice('{username}, {price}, {icon}, {newline}, {OR}', 'Available Dynamic Tags'), form.notice('{tip_text}', 'Available Tip Menu Tags'), form.notice('{lush_text}, {lush_duration}', 'Available Lovense Lush Level Tags'), ]; for (let num = 1; num <= nr_of_thank_you_messages; num++) { const prefix = 'thank_you_message_' + num + '_'; settings.push( form.subTitle('[' + letter + '.' + num + '] Tip Thank You Message ' + num), { name : prefix + 'enable', label : 'Enable', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'No', required : false }, { name : prefix + 'message', label : 'Message', type : 'str', required: false }, { name : prefix + 'in_tip_menus', label : 'Value should be in Tip Menus', type : 'choice', choice1 : 'Yes', choice2 : 'Optional', choice3 : 'No', defaultValue: 'No', required : false }, { name : prefix + 'fallback_text', label : '{tip_text} if item not in Tip Menus', type : 'str', defaultValue: 'Something Special', required : false }, { name : prefix + 'min_amount', label : 'Minimum Amount', type : 'int', defaultValue: 1, minValue : 1, maxValue : 99999999, required : false }, { name : prefix + 'max_amount', label : 'Maximum Amount (0 = no max)', type : 'int', defaultValue: 0, minValue : 0, maxValue : 99999999, required : false }, form.styles(prefix + 'style'), form.icons(prefix + 'icon'), form.userGroups(prefix + 'user_level', 'User Level of Tipper'), form.userGroupsPlusSelf(prefix + 'send_to_group', 'Tipper', 'Send Message to', 'Everyone') ); } return settings; }; getSettingsNoTipsMessages = function() { const letter = getNextSectionLetter(); const prefix = 'no_tips_message_'; return [ form.title('[' + letter + '] No Tips Messages'), { name : prefix + 'enable', label : 'Enable', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'Yes', required : false }, form.notice('{icon}, {newline}, {OR}', 'Available Dynamic Tags'), { name : prefix + 'message', label : 'Message', type : 'str', defaultValue: 'No tips, now show', required : false }, form.styles(prefix + 'style', null, 'Red Light'), form.icons(prefix + 'icon', null, 'Alarm'), { name : prefix + 'start', label : 'Start after time without tips (secs)', type : 'int', defaultValue: 600, minValue : 1, maxValue : 2400, required : false }, { name : prefix + 'interval', label : 'Interval (secs)', type : 'int', defaultValue: 600, minValue : 1, maxValue : 2400, required : false }, form.userGroups(prefix + 'send_to_group') ]; }; getSettingsSingleTips = function() { const letter = getNextSectionLetter(); const prefix = 'single_tip_'; return [ form.title('[' + letter + '] Random Single Tip Messages'), { name : prefix + 'enable', label : 'Enable', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'Yes', required : false }, form.notice('{price}, {text}, {icon}, {newline}, {OR}', 'Available Dynamic Tags'), { name : prefix + 'message', label : 'Message', type : 'str', defaultValue: '{price} tokens {icon} {text} {icon}', required : false }, { name : prefix + 'include_tip_menus', label : 'Include Tip Menu items', type : 'choice', choice1 : 'Yes', choice3 : 'No', defaultValue: 'Yes', required : false }, { name : prefix + 'include_lovense', label : 'Include Lovense Lush Level items', type : 'choice', choice1 : 'Yes', choice3 : 'No', defaultValue: 'Yes', required : false }, form.styles(prefix + 'style', null, 'Red Light'), form.icons(prefix + 'icon', null, 'Alarm'), { name : prefix + 'interval', label : 'Interval (secs)', type : 'int', defaultValue: 220, minValue : 1, maxValue : 1200, required : false }, { name : prefix + 'interval_offset', label : 'Offset (secs)', type : 'int', defaultValue: 0, minValue : 0, maxValue : 1200, required : false }, form.userGroups(prefix + 'send_to_group') ]; }; getSettingsTipMenus = function() { const letter = getNextSectionLetter(); const settings = [ form.title('[' + letter + '] Tip Menu\'s'), form.notice('{icon}, {newline}, {hideinmenu}...{/hideinmenu}', 'Available Dynamic Tags') ]; for (let num = 1; num <= nr_of_tip_menus; num++) { const prefix = 'tips_menu_' + num + '_'; settings.push( form.subTitle(num === 1 ? '[' + letter + '.1] Main Tip Menu' : '[' + letter + '.' + num + '] Tip Menu ' + num), { name : prefix + 'enable', label : 'Enable', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'No', required : false }, { name : prefix + 'interval', label : 'Interval (secs)', type : 'int', defaultValue: 300, minValue : 1, maxValue : 1200, required : false }, { name : prefix + 'interval_offset', label : 'Offset (secs)', type : 'int', defaultValue: 0, minValue : 0, maxValue : 1200, required : false } ); if (num !== 1) { settings.push( { name : prefix + 'skip_main', label : 'Skip if Main Menu auto-posted in last x secs', type : 'int', defaultValue: 0, minValue : 0, maxValue : 1200, required : false } ); } settings.push( form.styles(prefix + 'style'), form.icons(prefix + 'icon'), { name : prefix + 'title', label : 'Title', type : 'str', required: false }, { name : prefix + 'title_icons', label : 'Title Icons', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'No', required : false }, { name : prefix + 'layout', label : 'Layout', type : 'choice', choice1 : 'Horizontal', choice2 : 'Vertical', defaultValue: 'Vertical', required : false }, { name : prefix + 'footer', label : 'Footer', type : 'str', required: false }, { name : prefix + 'footer_separator', label : 'Footer Separator', type : 'choice', choice1 : '- None -', choice2 : 'Newline', choice3 : 'Icons', required: false }, { name : prefix + 'group_separator', label : 'Group Separator', type : 'choice', choice1 : '- None -', choice2 : 'Newline', choice3 : 'Icons', required: false }, { name : prefix + 'icon_line_length', label : 'Icon Line Length', type : 'int', defaultValue: 40, minValue : 10, maxValue : 100, required : false }, { name : prefix + 'price_separator', label : 'Price/Text Separator', type : 'choice', choice1 : '- None -', choice2 : 'Colon', choice3 : 'Dash', choice4 : 'Icon', required: false }, form.userGroups(prefix + 'send_to_group') ); settings.push( form.subSubTitle('Post on Entering'), { name : prefix + 'enter', label : 'Post on Entering', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'No', required : false }, { name : prefix + 'enter_delay', label : 'Delay (secs)', type : 'int', defaultValue: 0, minValue : 0, maxValue : 1200, required : false } ); settings.push( form.subSubTitle('Items'), form.notice('10 Item A; 20 Item B; etc...', 'Format') ); for (let line_num = 1; line_num <= nr_of_tip_menus_lines; line_num++) { let name = prefix + 'line_' + line_num; settings.push( { name : name, label : 'Group ' + line_num, type : 'str', required: false } ); } } return settings; }; getSettingsLovenseLevels = function() { const letter = getNextSectionLetter(); let prefix = 'lovense_'; const settings = [ form.title('[' + letter + '] Lovense Lush Levels'), form.styles(prefix + 'style'), form.lovenseStyles(prefix + 'icon_style'), { name : prefix + 'footer', label : 'Footer', type : 'str', required: false }, { name : prefix + 'footer_separator', label : 'Footer Separator', type : 'choice', choice1 : '- None -', choice2 : 'Newline', choice3 : 'Icons', required: false }, form.icons(prefix + 'footer_icon', 'Footer Icon', 'Star'), { name : prefix + 'icon_line_length', label : 'Icon Line Length', type : 'int', defaultValue: 40, minValue : 10, maxValue : 100, required : false }, form.userGroups(prefix + 'send_to_group') ]; settings.push( form.subSubTitle('Post on Entering'), { name : prefix + 'enter', label : 'Post on Entering', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'No', required : false }, { name : prefix + 'enter_delay', label : 'Delay (secs)', type : 'int', defaultValue: 0, minValue : 0, maxValue : 1200, required : false } ); settings.push( form.subSubTitle('Auto Post'), { name : prefix + 'auto', label : 'Auto Post', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'No', required : false }, { name : prefix + 'interval', label : 'Interval (secs)', type : 'int', defaultValue: 300, minValue : 1, maxValue : 1200, required : false }, { name : prefix + 'interval_offset', label : 'Offset (secs)', type : 'int', defaultValue: 0, minValue : 0, maxValue : 1200, required : false } ); prefix = 'lovense_levels_'; settings.push( form.subTitle('[' + letter + '.1] Lovense Lush Levels'), { name : prefix + 'title', label : 'Title', type : 'str', defaultValue: 'My Lovense Lush Levels', required : false }, { name : prefix + 'title_icons', label : 'Title Icons', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'No', required : false }, form.icons(prefix + 'icon'), { name : prefix + 'price_separator', label : 'Price/Text Separator', type : 'choice', choice1 : '- None -', choice2 : 'Colon', choice3 : 'Dash', choice4 : 'Icon', choice5 : 'Lush Icon', required: false }, form.notice('{icon}, {newline}, {icon}', 'Available Dynamic Tags') ); for (let num = 1; num <= nr_of_lovense_levels; num++) { const prefix = 'lovense_level_' + num + '_'; settings.push( form.subSubTitle('Level ' + num), { name : prefix + 'enable', label : 'Enable', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'Yes', required : false }, { name : prefix + 'level', label : 'Level', type : 'choice', choice1 : 'Low', choice2 : 'Medium', choice3 : 'High', choice4 : 'Ultra High', defaultValue: 'Low', required : false }, { name : prefix + 'price_from', label : 'Price From', type : 'int', defaultValue: 1, minValue : 1, maxValue : 999999, required : false }, { name : prefix + 'price_to', label : 'Price To (0 = no max)', type : 'int', defaultValue: 0, minValue : 0, maxValue : 999999, required : false }, { name : prefix + 'duration', label : 'Duration', type : 'int', defaultValue: 1, minValue : 1, maxValue : 1200, required : false } ); } prefix = 'lovense_patterns_'; settings.push( form.subTitle('[' + letter + '.2] Lovense Lush Patterns'), { name : prefix + 'title', label : 'Title', type : 'str', defaultValue: 'Patterns', required : false }, { name : prefix + 'title_icons', label : 'Title Icons', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'No', required : false }, form.icons(prefix + 'icon'), { name : prefix + 'price_separator', label : 'Price/Text Separator', type : 'choice', choice1 : '- None -', choice2 : 'Colon', choice3 : 'Dash', choice4 : 'Icon', choice5 : 'Lush Icon', required: false }, form.notice('{icon}, {newline}, {icon}', 'Available Dynamic Tags') ); for (let pattern of lovense_patterns) { prefix = 'lovense_pattern_' + pattern + '_'; settings.push( form.subSubTitle('Pattern: ' + pattern.toTitleCase()), { name : prefix + 'enable', label : 'Enable', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'Yes', required : false }, { name : prefix + 'price', label : 'Price', type : 'int', defaultValue: 100, minValue : 1, maxValue : 999999, required : false }, { name : prefix + 'duration', label : 'Duration', type : 'int', defaultValue: 30, minValue : 1, maxValue : 1200, required : false } ); } prefix = 'lovense_specials_'; settings.push( form.subTitle('[' + letter + '.3] Lovense Lush Specials'), { name : prefix + 'title', label : 'Title', type : 'str', defaultValue: 'Specials', required : false }, { name : prefix + 'title_icons', label : 'Title Icons', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'No', required : false }, form.icons(prefix + 'icon'), { name : prefix + 'price_separator', label : 'Price/Text Separator', type : 'choice', choice1 : '- None -', choice2 : 'Colon', choice3 : 'Dash', choice4 : 'Icon', choice5 : 'Lush Icon', required: false }, form.notice('{icon}, {newline}, {icon}', 'Available Dynamic Tags') ); for (let num = 1; num <= nr_of_lovense_specials; num++) { const prefix = 'lovense_special_' + num + '_'; settings.push( form.subSubTitle('Special ' + num), { name : prefix + 'enable', label : 'Enable', type : 'choice', choice1 : 'Yes', choice2 : 'No', defaultValue: 'No', required : false }, { name : prefix + 'description', label : 'Description', type : 'str', required: false }, form.icons(prefix + 'icon'), { name : prefix + 'price', label : 'Price', type : 'int', defaultValue: 1, minValue : 1, maxValue : 999999, required : false }, { name : prefix + 'duration', label : 'Duration', type : 'int', defaultValue: 60, minValue : 1, maxValue : 1200, required : false }, form.notice('{username}, {price}, {duration}, {description}, {icon}, {newline}, {OR}', 'Available Dynamic Tags'), { name : prefix + 'message', label : 'Extra Message on Tip', type : 'str', defaultValue: '', required : false }, form.styles(prefix + 'style'), form.userGroupsPlusSelf(prefix + 'send_to_group', 'Tipper') ); } return settings; }; function handleMessageQueue() { now += 1; addNoTipsMessagesToQueue(); for (let i in message_queue) { const message = message_queue[i]; if (message === '') { continue; } // one time message, remove after done if (!message.interval) { if (message.offset < now) { message.function(); // remove from queue message_queue[i] = null; } continue; } // now is still before the first message should trigger if (message.interval + message.offset > now) { continue; } // Skip if this is a tip menu and the main menu has shown recently if (message.name !== 'tips_menu_1' && message.name.indexOf('tips_menu_') === 0 && cb.settings[message.name + '_skip_main'] > 0 && now - last_main_tip_menu_shown < cb.settings[message.name + '_skip_main'] ) { continue; } // check if the interval (+ offset) equates to now, skip if it doesn't // add 1 to offset to deal with the second being added at the start of the function if ((now % message.interval) !== (message.offset + 1)) { continue; } if (message.name === 'tips_menu_1') { last_main_tip_menu_shown = now; } message.function(); } // remove null values from the queue (executed 1-time items) message_queue = message_queue.filter(function(el) { return el != null; }); updatePanel(); cb.setTimeout(handleMessageQueue, 1000); } function updateTipData(tip_data) { if (typeof tip_totals[tip_data.from_user] === 'undefined') { tip_totals[tip_data.from_user] = 0; } total_tipped += parseInt(tip_data.amount); tip_totals[tip_data.from_user] += parseInt(tip_data.amount); latest_tip = {'username': tip_data.from_user, 'amount': parseInt(tip_data.amount)}; all_tips.push(latest_tip); if (latest_tip.amount > highest_tip.amount) { highest_tip = latest_tip; } updateBestTippers(); updatePanel(); } function updateBestTippers() { // Get an array of the keys: let new_best_tippers_usernames = Object.keys(tip_totals); // Then sort by using the keys to lookup the values in the original object: new_best_tippers_usernames.sort(function(a, b) { return tip_totals[b] - tip_totals[a]; }); new_best_tippers = []; for (let username of new_best_tippers_usernames) { new_best_tippers.push({'username': username, 'amount': parseInt(tip_totals[username])}); } const max = parseInt(cb.settings['leader_board_max']); let is_changed = JSON.stringify(best_tippers_usernames.slice(0, max)) !== JSON.stringify(new_best_tippers_usernames.slice(0, max)); best_tippers = new_best_tippers; best_tippers_usernames = new_best_tippers_usernames; if (is_changed) { showLeaderBoardOnChange(); } } function getTopTippers(max = 3) { return best_tippers.slice(0, max); } function updatePanel() { cb.drawPanel(); } cb.onDrawPanel(function(user) { const prefix = 'panel_settings_'; const timeout = parseInt(cb.settings[prefix + 'timeout']); let panels = []; if (cb.settings[prefix + 'show_goals'] === 'Yes') { const panel = drawPanelGoals(); if (panel !== false) { panels.push(panel); } } if (cb.settings[prefix + 'show_totals'] === 'Yes') { const panel = drawPanelTotals(); if (panel !== false) { panels.push(panel); } } if (cb.settings[prefix + 'show_leader_board'] === 'Yes') { const panel = drawPanelLeaderBoard(); if (panel !== false) { panels.push(panel); } } if (!panels.length) { return; } if (panels.length === 1) { return panels[0]; } let cycle_time = panels.length * timeout; let panel_number = Math.floor((now % cycle_time) / timeout); return typeof panels[panel_number] !== 'undefined' ? panels[panel_number] : panels[0]; }); function drawPanelGoals() { const goal = getCurrentGoal(); if (!goal) { return false; } const prefix = 'panel_settings_'; const goal_text = getIcon(prefix + 'icon_goal') //+ ' #' + goal.number + ' ' + goal.description + ' (' + goal.tipped + '/' + goal.amount + ')'; const progress_text = getPercentageIcons(goal.percentage) + ' ' + goal.percentage + '%'; const remaining_text = getIcon(prefix + 'icon_remaining') + ' ' + goal.remaining + ' tokens'; return drawPanel( (goal.remaining ? 'Next Goal:' : 'Goal Reached:'), goal_text, 'Progress:', progress_text, 'Remaining:', remaining_text ); } function drawPanelTotals() { const prefix = 'panel_settings_'; let best_tipper_title = ''; let best_tipper_text = ''; let highest_tip_label = 'Will you be the first tipper?'; let highest_tip_text = ''; let latest_tip_label = ''; let latest_tip_text = ''; if (best_tippers.length && best_tippers[0].amount) { best_tipper_title = 'Best Tipper:'; best_tipper_text = getIcon(prefix + 'icon_best_tipper') + ' ' + best_tippers[0].username + ' (' + best_tippers[0].amount + ')'; } if (highest_tip.amount) { highest_tip_label = 'Highest Tip:'; highest_tip_text = getIcon(prefix + 'icon_highest_tip') + ' ' + highest_tip.username + ' (' + highest_tip.amount + ')'; } if (latest_tip.amount) { latest_tip_label = 'Latest Tip:'; latest_tip_text = getIcon(prefix + 'icon_latest_tip') + ' ' + latest_tip.username + ' (' + latest_tip.amount + ')'; } return drawPanel( best_tipper_title, best_tipper_text, highest_tip_label, highest_tip_text, latest_tip_label, latest_tip_text ); } function drawPanelLeaderBoard() { const prefix = 'panel_settings_'; const top_tippers = getTopTippers(); if (!top_tippers.length) { return false; } let leader_board_1_title = 'Best Tipper #1:'; let leader_board_1_text = '...'; let leader_board_2_title = '#2:'; let leader_board_2_text = '...'; let leader_board_3_title = '#3:'; let leader_board_3_text = '...'; if (typeof top_tippers[0] !== 'undefined') { leader_board_1_text = top_tippers[0].username + ' (' + top_tippers[0].amount + ')'; } if (typeof top_tippers[1] !== 'undefined') { leader_board_2_text = top_tippers[1].username + ' (' + top_tippers[1].amount + ')'; } if (typeof top_tippers[2] !== 'undefined') { leader_board_3_text = top_tippers[2].username + ' (' + top_tippers[2].amount + ')'; } return drawPanel( leader_board_1_title, getIcon(prefix + 'icon_leader_board_1') + ' ' + leader_board_1_text, leader_board_2_title, getIcon(prefix + 'icon_leader_board_2') + ' ' + leader_board_2_text, leader_board_3_title, getIcon(prefix + 'icon_leader_board_3') + ' ' + leader_board_3_text ); } function drawPanel( label1, text1, label2, text2, label3, text3 ) { const prefix = 'panel_settings_'; const padding = 5; const gap = 5; const full_width = 270 - (padding * 2); const title_width = 90; const title_left_offset = padding; const text_left_offset = padding + title_width + gap; const text_width = full_width - title_width - gap; // Temporary fix for offset due to emojis in Edge/Chrome // Edge/Chrome actually need a correction of -4 // But Firefox doesn't need the offset, so now the both have a 'medium' offset vertical_offset_text = -2; return { "template": "image_template", "layers" : [ {'type': 'image', 'fileID': '9f9c56b0-c81a-46a9-85db-0cd515c18b25'}, { 'type' : 'text', 'text' : label1, 'top' : 7, 'left' : title_left_offset, 'width' : text1 ? title_width : full_width, 'text-align' : text1 ? 'right' : 'center', 'font-size' : 12, 'font-weight': 'bold', 'color' : getColor(prefix + 'color_title_1') }, { 'type' : 'text', 'text' : label2, 'top' : 28, 'left' : title_left_offset, 'width' : text2 ? title_width : full_width, 'text-align' : text2 ? 'right' : 'center', 'font-size' : 12, 'font-weight': 'bold', 'color' : getColor(prefix + 'color_title_2') }, { 'type' : 'text', 'text' : label3, 'top' : 49, 'left' : title_left_offset, 'width' : text3 ? title_width : full_width, 'text-align' : text3 ? 'right' : 'center', 'font-size' : 12, 'font-weight': 'bold', 'color' : getColor(prefix + 'color_title_3') }, { 'type' : 'text', 'text' : text1, 'top' : 7 + vertical_offset_text, 'left' : text_left_offset, 'width' : text_width, 'font-size': 12, // 'line-height': 14, 'color' : getColor(prefix + 'color_text_1') }, { 'type' : 'text', 'text' : text2, 'top' : 28 + vertical_offset_text, 'left' : text_left_offset, 'width' : text_width, 'font-size': 12, // 'line-height': 14, 'color' : getColor(prefix + 'color_text_2') }, { 'type' : 'text', 'text' : text3, 'top' : 49 + vertical_offset_text, 'left' : text_left_offset, 'width' : text_width, 'font-size': 12, // 'line-height': 14, 'color' : getColor(prefix + 'color_text_3') } ] }; } function getTotalGoalsReached() { if (!total_tipped) { return 0; } const goal_amount = parseInt(cb.settings['goals_amount']); return Math.floor(total_tipped / goal_amount); } function getCurrentGoal() { if (!goals.length) { return false; } const goal_amount = parseInt(cb.settings['goals_amount']); const already_tipped = getCurrentTipsForGoal(); const total_reached = getTotalGoalsReached(); let id = total_reached % goals.length; if (total_tipped >= goal_amount && already_tipped == goal_amount) { id = (total_reached - 1) % goals.length; } return { 'id' : id, 'number' : total_reached + 1, 'description': goals[id], 'amount' : goal_amount, 'tipped' : already_tipped, 'percentage' : getCurrentTipsForGoalPercentage(), 'remaining' : goal_amount - already_tipped, }; } function getPreviousGoal() { if (!goals.length) { return false; } const goal_amount = parseInt(cb.settings['goals_amount']); const total_reached = getTotalGoalsReached(); const id = (total_reached - 1) % goals.length; return { 'id' : id, 'number' : total_reached, 'description': goals[id], 'amount' : goal_amount, 'tipped' : goal_amount, 'percentage' : 100, 'remaining' : 0, }; } function getCurrentTipsForGoal() { const goal_amount = parseInt(cb.settings['goals_amount']); return ((total_tipped - 1) % goal_amount) + 1; } function getCurrentTipsForGoalPercentage() { const goal_amount = parseInt(cb.settings['goals_amount']); const already_tipped = getCurrentTipsForGoal(); return already_tipped ? Math.floor((already_tipped / goal_amount) * 100) : 0; } function getPercentageIcons(percentage) { const prefix = 'panel_settings_'; const tipped = percentage ? Math.floor(percentage / 10) : 0; const remaining = 10 - tipped; if (!remaining && cb.settings[prefix + 'icon_progress_multicolor'] === 'Yes') { return ( getIcon('heart orange') + getIcon('heart yellow') + getIcon('heart green') + getIcon('heart blue') + getIcon('heart purple') ).repeat(2); } return getIcon(prefix + 'icon_progress_completed').repeat(tipped) + getIcon(prefix + 'icon_progress_empty').repeat(remaining); } function addWelcomeMessagesToQueue(user) { if (!user) { return; } for (let num = 1; num <= nr_of_welcome_messages; num++) { const prefix = 'welcome_message_' + num + '_'; if (cb.settings[prefix + 'enable'] !== 'Yes' || cb.settings[prefix + 'message'] === '' ) { continue; } message_queue.push( { 'name' : prefix + '' + user.user, 'offset' : now + cb.settings[prefix + 'delay'], 'interval': 0, 'function': function() { showWelcomeMessage(num, user); } } ); } } function showLeaderBoardOnChange() { const prefix = 'leader_board_'; if (cb.settings[prefix + 'post_on_change'] !== 'Yes') { return; } showLeaderBoard(); } function addLeaderBoardToQueue() { const prefix = 'leader_board_'; if (cb.settings[prefix + 'post_on_change'] !== 'Yes') { return; } message_queue.push( { 'name' : 'leader_board', 'offset' : cb.settings[prefix + 'interval_offset'], 'interval': cb.settings[prefix + 'interval'], 'function': function() { showLeaderBoard(); } } ); } function addRotatingMessagesToQueue() { for (let num = 1; num <= nr_of_rotating_message; num++) { const prefix = 'rotating_message_' + num + '_'; if (cb.settings[prefix + 'enable'] !== 'Yes' || cb.settings[prefix + 'message'] === '' ) { continue; } message_queue.push( { 'name' : 'rotating_message_' + num, 'offset' : cb.settings[prefix + 'interval_offset'], 'interval': cb.settings[prefix + 'interval'], 'function': function() { showRotatingMessage(num); } } ); } } function showGoalMessage(tip_data) { let goal = getCurrentGoal(); if (!goal) { return false; } if (!goal.remaining || goal.tipped < tip_data.amount) { if (goal.remaining) { goal = getPreviousGoal(); } showGoalReachedMessage(tip_data, goal); return; } showGoalUpdatedMessage(tip_data, goal); } function showThankYouMessages(tip_data) { for (let num = 1; num <= nr_of_thank_you_messages; num++) { const prefix = 'thank_you_message_' + num + '_'; if (cb.settings[prefix + 'enable'] !== 'Yes' || cb.settings[prefix + 'message'] === '' ) { continue; } const min = parseInt(cb.settings[prefix + 'min_amount']); const max = parseInt(cb.settings[prefix + 'max_amount']); if (parseInt(tip_data.amount) < min || (max && parseInt(tip_data.amount) > max) ) { continue; } showThankYouMessage(num, tip_data); } for (let num = 1; num <= nr_of_lovense_specials; num++) { const prefix = 'lovense_special_' + num + '_'; if (cb.settings[prefix + 'enable'] !== 'Yes') { continue; } const price = cb.settings[prefix + 'price']; if (parseInt(tip_data.amount) !== parseInt(price)) { continue; } let message = getMessageByPrefix(prefix); message = message.replace(/{price}/g, price); message = message.replace(/{duration}/g, getDuration[prefix + 'duration']); message = message.replace(/{description}/g, getText[prefix + 'description']); sendNoticeByUserGroup(message, prefix, tip_data.from_user, 'Tipper'); } } function addMessageToQueueOnce(func, delay = 0) { message_queue.push( { 'name' : '', 'offset' : now + delay, 'interval': 0, 'function': func } ); } function addNoTipsMessagesToQueue() { const prefix = 'no_tips_message_'; if (cb.settings[prefix + 'enable'] !== 'Yes') { return; } const time_ago = now - last_tip_time; const start = parseInt(cb.settings[prefix + 'start']); const interval = parseInt(cb.settings[prefix + 'interval']); if (time_ago < start) { return; } // check if the time_ago is not equal to now // or matches the interval if (time_ago !== start && ((time_ago - start) % interval) !== 0 ) { return; } message_queue.push( { 'name' : 'no_tips_message', 'offset' : now, 'interval': 0, 'function': function() { showNoTipsMessage(); } } ); } function addSingleTipsToQueue() { const prefix = 'single_tip_'; if (!tip_items.tip_menu_items.length && !tip_items.lovense_items.length) { return; } if (cb.settings[prefix + 'enable'] !== 'Yes') { return; } message_queue.push( { 'name' : 'single_tips', 'offset' : cb.settings[prefix + 'interval_offset'], 'interval': cb.settings[prefix + 'interval'], 'function': function() { showSingleTip(); } } ); } function addTipMenusOnEnterToQueue(user) { for (let num = 1; num <= nr_of_tip_menus; num++) { const prefix = 'tips_menu_' + num + '_'; if (cb.settings[prefix + 'enable'] !== 'Yes' || cb.settings[prefix + 'enter'] !== 'Yes' || cb.settings[prefix + 'line_1'] === '' ) { continue; } addMessageToQueueOnce(function() { showTipMenu(num, user); }, cb.settings[prefix + 'enter_delay']); } } function addLovenseLevelsOnEnterToQueue(user) { const prefix = 'lovense_'; if (cb.settings[prefix + 'enter'] !== 'Yes') { return; } addMessageToQueueOnce(function() { showLovenseLevels(user); }, cb.settings[prefix + 'enter_delay']); } function addTipMenusToQueue() { for (let num = 1; num <= nr_of_tip_menus; num++) { const prefix = 'tips_menu_' + num + '_'; if (cb.settings[prefix + 'enable'] !== 'Yes' || cb.settings[prefix + 'line_1'] === '' ) { continue; } message_queue.push({ 'name' : 'tips_menu_' + num, 'offset' : cb.settings[prefix + 'interval_offset'], 'interval': cb.settings[prefix + 'interval'], 'function': function() { showTipMenu(num); } }); } } function addLovenseLevelsToQueue() { const prefix = 'lovense_'; if (cb.settings[prefix + 'auto'] !== 'Yes') { return; } message_queue.push({ 'name' : 'lovense', 'offset' : cb.settings[prefix + 'interval_offset'], 'interval': cb.settings[prefix + 'interval'], 'function': function() { showLovenseLevels(); } }); } function showLeaderBoard() { const prefix = 'leader_board_'; const min = parseInt(cb.settings[prefix + 'min']); if (best_tippers.length < min) { return; } const top_tippers = getTopTippers(parseInt(cb.settings[prefix + 'max'])); const style = getStyle(prefix + 'style'); const icon = getIcon(prefix + 'icon'); const line_length = parseInt(cb.settings[prefix + 'icon_line_length']); const footer_separator = getSeparator(prefix + 'footer_separator', icon, line_length); let tippers_output = []; for (let i in top_tippers) { tippers_output.push( icon + ' #' + (parseInt(i) + 1) + ' : ' + top_tippers[i].username + ' (' + top_tippers[i].amount + ')' ); } let title = getText(prefix + 'title'); let footer = getText(prefix + 'footer'); if (cb.settings[prefix + 'title_icons'] === 'Yes') { title = getIconTitle(title, icon, line_length); } let output = title + (title ? '\n' : '') + tippers_output.join('\n') + (footer_separator || footer ? '\n' : '') + footer_separator + footer; const send_to_group = getUserGroupByName(prefix + 'send_to_group'); sendNotice(output, null, false, send_to_group, style, icon); } function showWelcomeMessage(num = 1, user = null) { const prefix = 'welcome_message_' + num + '_'; const message = getMessageByPrefix(prefix); if (message === '') { return; } let user_level = getUserGroupByName(prefix + 'user_level'); if (user !== null && userPassesGroup(user, user_level)) { return; } sendNoticeByUserGroup(message, prefix, user, 'Visitor'); } function showRotatingMessage(num = 1) { const prefix = 'rotating_message_' + num + '_'; const message = getMessageByPrefix(prefix); const send_to_group = getUserGroupByName(prefix + 'send_to_group'); const style = getStyle(prefix + 'style'); const icon = getIcon(prefix + 'icon'); sendNotice(message, null, false, send_to_group, style, icon); } function showNewFollowerMessage(user) { const prefix = 'new_follower_messages_'; if (cb.settings[prefix + 'enable'] !== 'Yes') { return; } const message = getMessageByPrefix(prefix); if (message === '') { return; } let user_level = getUserGroupByName(prefix + 'user_level'); /// check if user is in groups? if (user !== null && !userPassesGroup(user, user_level)) { return; } sendNoticeByUserGroup(message, prefix, user, 'Follower'); } function showGoalReachedMessage(tip_data, goal) { const prefix = 'goals_message_on_reached_'; showGoalMessageByType(prefix, tip_data, goal); } function showGoalUpdatedMessage(tip_data, goal) { const prefix = 'goals_message_on_update_'; const min = parseInt(cb.settings[prefix + 'min_amount']); if (parseInt(tip_data.amount) < parseInt(min)) { return; } showGoalMessageByType(prefix, tip_data, goal); } function showGoalMessageByType(prefix, tip_data, goal) { if (cb.settings[prefix + 'enable'] !== 'Yes') { return ''; } let message = getMessageByPrefix(prefix); if (message === '') { return; } message = message.replace(/{tipped}/g, tip_data.amount); message = message.replace(/{goal}/g, goal.description); message = message.replace(/{goal_amount}/g, goal.amount); message = message.replace(/{goal_remaining}/g, goal.remaining); const send_to_group = getUserGroupByName(prefix + 'send_to_group'); const style = getUserGroupByName(prefix + 'style'); const icon = getUserGroupByName(prefix + 'icon'); const username = tip_data.is_anon_tip ? 'anonymous user' : tip_data.from_user; sendNotice(message, username, false, send_to_group, style, icon); } function showThankYouMessage(num = 1, tip_data = null) { const prefix = 'thank_you_message_' + num + '_'; const message = getThankYouMessage(num, tip_data); if (message === '') { return; } let user = getUserByName(tip_data.from_user); let user_level = getUserGroupByName(prefix + 'user_level'); /// check if user is in groups? if (user !== null && !userPassesGroup(user, user_level)) { return; } sendNoticeByUserGroup(message, prefix, user, 'Tipper'); } function getUserByName(user) { if (!user) { return null; } if (typeof user_objects[user] === 'undefined') { return null; } return user_objects[user]; } function showNoTipsMessage() { const prefix = 'no_tips_message_'; const message = getMessageByPrefix(prefix); const send_to_group = getUserGroupByName(prefix + 'send_to_group'); const style = getUserGroupByName(prefix + 'style'); const icon = getUserGroupByName(prefix + 'icon'); sendNotice(message, null, false, send_to_group, style, icon); } function showSingleTip() { const prefix = 'single_tip_'; const message = getSingleTip(); const send_to_group = getUserGroupByName(prefix + 'send_to_group'); const style = getUserGroupByName(prefix + 'style'); const icon = getUserGroupByName(prefix + 'icon'); sendNotice(message, null, false, send_to_group, style, icon); } function showTipMenu(num = 1, user = null) { const prefix = 'tips_menu_' + num + '_'; const message = getTipMenu(num); const send_to_group = getUserGroupByName(prefix + 'send_to_group'); const style = getUserGroupByName(prefix + 'style'); const icon = getUserGroupByName(prefix + 'icon'); sendNotice(message, user, user !== null, send_to_group, style, icon); } function showLovenseLevels(user = null) { const prefix = 'lovense_'; let message = getLovenseLevels(); let send_to_group = getUserGroupByName(prefix + 'send_to_group'); let style = getUserGroupByName(prefix + 'style'); sendNotice(message, user, user !== null, send_to_group, style); } function log(message, user = null) { sendNotice(message, user, user !== null, 'owner_mods', 'Red'); } function sendNotice(message, user, send_to_user, send_to_group, style = '', icon = '', weight = 'bold') { send_to_group = getUserGroupByName(send_to_group); if (!send_to_group && !send_to_user) { sendNoticeToEveryone(message, user, style, icon, weight); return; } if (!send_to_user) { sendNoticeToGroup(message, send_to_group, style, icon, weight); return; } if (!send_to_group) { sendNoticeToUser(message, user, style, icon, weight); return; } sendNoticeToUserInGroup(message, user, send_to_group, style, icon, weight); } function sendNoticeByUserGroup(message, prefix, user = null, self_name = 'None', send_to_group_name = 'send_to_group') { const style = cb.settings[prefix + 'style']; const icon = cb.settings[prefix + 'icon']; const send_to_group = cb.settings[prefix + send_to_group_name]; switch (send_to_group) { case self_name: sendNotice(message, user, true, null, style, icon); return; case self_name + ' & Room Owner': sendNotice(message, user, true, null, style, icon); sendNotice(message, user, false, 'room_owner', style, icon); return; case self_name + ' & Room Owner & Moderators': sendNotice(message, user, true, null, style, icon); sendNotice(message, user, false, 'owner_mods', style, icon); return; default: sendNotice(message, user, false, getUserGroupByName(send_to_group), style, icon); return; } } function sendNoticeToEveryone(message, user, style, icon, weight = 'bold') { let user_name = getUserName(user); style = getStyle(style); icon = getIcon(icon); cb.sendNotice(prepareMessage(message, user_name, icon), null, style.background, style.color, weight); } function sendNoticeToUser(message, user, style, icon, weight = 'bold') { let user_name = getUserName(user); style = getStyle(style); icon = getIcon(icon); cb.sendNotice(prepareMessage(message, user_name, icon), user_name, style.background, style.color, weight); } function sendNoticeToUserInGroup(message, user, send_to_group, style, icon, weight = 'bold') { if (user !== null && !userPassesGroup(user, send_to_group)) { return; } let user_name = getUserName(user); style = getStyle(style); icon = getIcon(icon); cb.sendNotice(prepareMessage(message, user_name, icon), user_name, style.background, style.color, weight); } function sendNoticeToGroup(message, send_to_group, style, icon, weight = 'bold') { if (send_to_group === 'owner_mods') { sendNoticeToGroup(message, 'moderator', style, weight); sendNoticeToGroup(message, 'room_owner', style, weight); return; } style = getStyle(style); icon = getIcon(icon); if (['grey', 'moderator', 'room_owner'].indexOf(send_to_group) === -1) { cb.sendNotice(prepareMessage(message, null, icon), null, style.background, style.color, weight, send_to_group); return; } if (typeof room_users[send_to_group] === 'undefined') { return; } for (let user of room_users[send_to_group]) { cb.sendNotice(prepareMessage(message, user, icon), user, style.background, style.color, weight); } } function prepareMessage(message, user_name = null, icon = '') { if (typeof message !== 'string') { return message; } if (user_name) { message = message.replace(/{username}/g, user_name); } message = message.replace(/{newline}/g, '\n') // replace {newline} tags .replace(/{icon}/g, icon) // replace {icon} tags .replace(/{username}/g, '') // remove remaining {username} tags .replace(/^( *\n+ *)+/g, '') // remove leading whitespace .replace(/( *\n+ *)+$/g, ''); // remove trailing whitespace getMatches(message, /{icon:([^}]+)}/g).forEach((match) => { message = message.replace(match[0], getIcon(match[1])); }); return message; } function getMatches(str, regex) { let matches = []; do { match = regex.exec(str); if (match) { matches.push(match); } } while (match); return matches; } function getText(text) { if (typeof cb.settings[text] !== 'undefined') { text = cb.settings[text]; } text = getRandomMessagePart(text); return text; } function getRandomMessagePart(message) { messages = message.split('{OR}'); return messages[Math.floor(Math.random() * messages.length)]; } function addIconsToText(message, icon) { if (icon === '') { return message; } message = message.replace(/({newline}|\n)/g, '\n' + icon + ' '); return icon + ' ' + message; } function removeHiddenMenuText(message) { return message.replace(/{hideinmenu}.*?{\/hideinmenu}/g, ''); } function removeHiddenMenuTextTags(message) { return message.replace(/{\/?hideinmenu}/g, ''); } function updateUsersList(user) { cb.getRoomUsersData(usersData => { if (!usersData.success) { return; } room_users = usersData.data; }); user_objects[user.user] = user; } function userPassesGroup(user, group) { if (user === null) { return false; } if (typeof user === 'string') { user = getUserByName(user); } if (user === null || typeof user !== 'object' || typeof user.user === 'undefined') { // ignore if user is not a user object return false; } switch (group) { case 'grey': return !user.has_tokens; case 'lightblue': return user.has_tokens; case 'darkblue': return user.tipped_recently; case 'lightpurple': return user.tipped_alot_recently; case 'darkpurple': return user.tipped_tons_recently; case 'green': return user.in_fanclub; case 'moderator': return userIsInGroupData(user.user, 'moderator'); case 'room_owner': return userIsInGroupData(user.user, 'room_owner'); case 'owner_mods': return userIsInGroupData(user.user, 'moderator') || userIsInGroupData(user.user, 'room_owner'); default: return true; } } function userIsInGroupData(user_name, user_group) { if (typeof room_users[user_group] === 'undefined') { return; } return room_users[user_group].indexOf(user_name) !== -1; } function getMessageByPrefix(prefix) { const message = getText(prefix + 'message'); if (message === '') { return ''; } const icon = getIcon(prefix + 'icon'); return addIconsToText(message, icon); } function getThankYouMessage(num = 1, tip_data = null) { const prefix = 'thank_you_message_' + num + '_'; const include_anonymous = cb.settings['thank_you_messages_include_anonymous']; if (!include_anonymous && tip_data.is_anon_tip) { return ''; } let data = getTipData( tip_data.amount, cb.settings[prefix + 'fallback_text'] ); if (!data.is_tip && cb.settings[prefix + 'in_tip_menus'] === 'Yes') { return ''; } if (data.is_tip && cb.settings[prefix + 'in_tip_menus'] === 'No') { return ''; } let message = getText(prefix + 'message'); if (message === '') { return ''; } const username = tip_data.is_anon_tip ? cb.settings['thank_you_messages_anonymous_name'] : tip_data.from_user; const icon = getIcon(prefix + 'icon'); message = message.replace(/{price}/g, data.price); message = message.replace(/{amount}/g, data.price); message = message.replace(/{username}/g, username); for (let key in data) { const regexp = new RegExp('{' + key + '}', 'g'); message = message.replace(regexp, data[key]); } return addIconsToText(message, icon); } function getSingleTip() { const prefix = 'single_tip_'; if (!cb.settings[prefix + 'include_tip_menus'] && !cb.settings[prefix + 'include_lovense'] ) { return ''; } let message = getText(prefix + 'message'); const icon = getIcon(prefix + 'icon'); const types = []; if (cb.settings[prefix + 'include_tip_menus']) { types.push('tip_menu_items'); } if (cb.settings[prefix + 'include_lovense']) { types.push('lovense_items'); } const tip = getSingleTipByType(types[Math.floor(Math.random() * types.length)]); if (!tip) { return ''; } message = message.replace(/{price}/g, tip.price); message = message.replace(/{text}/g, removeHiddenMenuTextTags(tip.text)); return addIconsToText(message, icon); } function getSingleTipByType(id) { if (!tip_items[id].length) { return ''; } if (typeof random[id] === 'undefined' || !random[id].length) { random[id] = tip_items[id].slice(0); } const pos = Math.floor(Math.random() * random[id].length); const tip = random[id][pos]; // remove tip, so it doesn't get repeated random[id].splice(pos, 1); return tip; } function getSingleTipFromLovense(message) { if (!all_lovense.length) { return ''; } if (typeof random.lovense === 'undefined' || !random.lovense.length) { random.lovense = all_lovense.slice(0); } const pos = Math.floor(Math.random() * random.lovense.length); const tip = random.lovense[pos]; // remove tip, so it doesn't get repeated random.lovense.splice(pos, 1); return tip; } function getTipMenu(num = 1) { const prefix = 'tips_menu_' + num + '_'; if (cb.settings[prefix + 'enable'] !== 'Yes') { return; } let tip_groups = []; for (let line_num = 1; line_num <= nr_of_tip_menus_lines; line_num++) { let line = cb.settings[prefix + 'line_' + line_num]; if (!line) { continue; } const tips = getTipLinesFromString(line); if (!tips) { continue; } tip_groups.push(tips); } if (!tip_groups.length) { return; } const layout = cb.settings[prefix + 'layout']; const icon = getIcon(prefix + 'icon'); const line_length = parseInt(cb.settings[prefix + 'icon_line_length']); const item_separator = layout === 'Horizontal' ? ' ' : '\n'; const price_separator = getSeparator(prefix + 'price_separator', icon, line_length, layout); const group_separator = getSeparator(prefix + 'group_separator', icon, line_length, layout); const footer_separator = getSeparator(prefix + 'footer_separator', icon, line_length, layout); let groups = []; for (tip_objects of tip_groups) { const tips = []; for (tip of tip_objects) { tips.push(icon + ' ' + tip.price + price_separator + tip.text); } groups.push(tips.join(item_separator)); } let tips_block = groups.join(item_separator + group_separator); let title = getText(prefix + 'title'); let footer = getText(prefix + 'footer'); if (cb.settings[prefix + 'title_icons'] === 'Yes') { title = getIconTitle(title, icon, line_length); } if (layout === 'Horizontal') { tips_block += ' ' + icon; } let output = title + (title ? '\n' : '') + tips_block + (footer_separator || footer ? '\n' : '') + footer_separator + footer; output = removeHiddenMenuText(output); return output; } function getIconTitle(title, icon, line_length = 40) { let padding_length = line_length; const title_length = getTextLength(title); if (title_length) { // count title length for 80% because of possible narrow letters padding_length -= (title_length * .8); } padding_length = Math.floor(padding_length / 4); if (padding_length < 1) { return title; } return (icon + ' ').repeat(padding_length) + title + (' ' + icon).repeat(padding_length); } function getTextLength(str) { // Replace images with XX to assume some width str = str.replace(/:[a-z0-9-_]+/g, 'XX'); return str.length; } function getTipLinesFromString(str) { let tips = []; const items = str.split(';'); for (item of items) { const match = item.trim().match(/^([0-9]+) (.*)$/); if (!match) { continue; } tips.push({ 'price': match[1], 'text' : match[2] }); } return tips; } function getTipData(price, default_tip_text = '') { let tip = getTipDataByPrice(price); let lovense_data = getLovenseDataByPrice(price); return { 'price' : price, 'is_tip' : tip.is_tip, 'tip_text' : tip.is_tip ? tip.text : default_tip_text, 'lush_text' : lovense_data.text, 'lush_duration': lovense_data.duration, }; } function getTipDataByPrice(price) { if (!tip_items.tip_menu_items.length) { return { 'text' : '', 'is_tip': false, }; } for (let tip of tip_items.tip_menu_items) { if (parseInt(tip.price) === parseInt(price)) { return { 'text' : tip.text, 'is_tip': true, }; } } return { 'text' : '', 'is_tip': false, }; } function getLovenseDataByPrice(price) { for (let num = 1; num <= nr_of_lovense_specials; num++) { const prefix = 'lovense_special_' + num + '_'; if (cb.settings[prefix + 'enable'] !== 'Yes') { continue; } const item_price = cb.settings[prefix + 'price']; if (parseInt(item_price) === parseInt(price)) { return { 'text' : getText(prefix + 'description'), 'duration': getDuration(prefix + 'duration'), }; } } for (let pattern of lovense_patterns) { const prefix = 'lovense_pattern_' + pattern + '_'; if (cb.settings[prefix + 'enable'] !== 'Yes') { continue; } const item_price = cb.settings[prefix + 'price']; if (parseInt(item_price) === parseInt(price)) { return { 'text' : pattern.toTitleCase(), 'duration': getDuration(prefix + 'duration'), }; } } for (let num = 1; num <= nr_of_lovense_levels; num++) { const prefix = 'lovense_level_' + num + '_'; if (cb.settings[prefix + 'enable'] !== 'Yes') { continue; } const price_from = cb.settings[prefix + 'price_from']; const price_to = cb.settings[prefix + 'price_to']; if (parseInt(price) >= parseInt(price_from) && (!price_to || parseInt(price) <= parseInt(price_to)) ) { return { 'text' : cb.settings[prefix + 'level'].toTitleCase(), 'duration': getDuration(prefix + 'duration'), }; } } return { 'text' : '', 'duration': 0, }; } function getLovenseLevels() { const prefix = 'lovense_'; let lines = []; const icon_style = cb.settings[prefix + 'icon_style']; const line_length = parseInt(cb.settings[prefix + 'icon_line_length']); // LEVELS let levels = []; let price_separator = getSeparator('lovense_levels_price_separator'); for (let num = 1; num <= nr_of_lovense_levels; num++) { const prefix = 'lovense_level_' + num + '_'; if (cb.settings[prefix + 'enable'] !== 'Yes') { continue; } const level = cb.settings[prefix + 'level']; const price_from = cb.settings[prefix + 'price_from']; const price_to = cb.settings[prefix + 'price_to']; const duration = getDuration(prefix + 'duration'); const price = price_from + (price_to ? '-' + price_to : '+'); levels.push( getLovenseIcon(num, icon_style) + ' ' + price + price_separator + level.toTitleCase() + ' (' + duration + ')' ); } if (levels.length) { const prefix = 'lovense_levels_'; let title = getText(prefix + 'title'); const icon = getIcon(prefix + 'icon'); if (cb.settings[prefix + 'title_icons'] === 'Yes') { title = getIconTitle(title, icon, line_length); } levels = addIconsToText(levels.join('\n'), icon); lines.push(title); lines.push(levels); } // PATTERNS let patterns = []; price_separator = getSeparator('lovense_patterns_price_separator'); for (let pattern of lovense_patterns) { const prefix = 'lovense_pattern_' + pattern + '_'; if (cb.settings[prefix + 'enable'] !== 'Yes') { continue; } const price = cb.settings[prefix + 'price']; const duration = getDuration(prefix + 'duration'); patterns.push( getLovenseIcon(pattern, icon_style) + ' ' + price + price_separator + pattern.toTitleCase() + ' (' + duration + ')' ); } if (patterns.length) { const prefix = 'lovense_patterns_'; let title = getText(prefix + 'title'); const icon = getIcon(prefix + 'icon'); if (cb.settings[prefix + 'title_icons'] === 'Yes') { title = getIconTitle(title, icon, line_length); } patterns = addIconsToText(patterns.join('\n'), icon); lines.push(title); lines.push(patterns); } // SPECIALS let specials = []; price_separator = getSeparator('lovense_specials_price_separator'); for (let num = 1; num <= nr_of_lovense_specials; num++) { const prefix = 'lovense_special_' + num + '_'; if (cb.settings[prefix + 'enable'] !== 'Yes') { continue; } const special = cb.settings[prefix + 'description']; const special_icon = getIcon(prefix + 'icon'); const price = cb.settings[prefix + 'price']; const duration = getDuration(prefix + 'duration'); specials.push( special_icon + ' ' + price + price_separator + special.toTitleCase() + ' (' + duration + ')' ); } if (specials.length) { const prefix = 'lovense_specials_'; let title = getText(prefix + 'title'); const icon = getIcon(prefix + 'icon'); if (cb.settings[prefix + 'title_icons'] === 'Yes') { title = getIconTitle(title, icon, line_length); } specials = addIconsToText(specials.join('\n'), icon); lines.push(title); lines.push(specials); } if (!lines.length) { return; } const footer = getText(prefix + 'footer'); const footer_icon = getIcon(prefix + 'footer_icon'); const footer_separator = getSeparator(prefix + 'footer_separator', footer_icon, line_length); lines.push(footer_separator + footer); output = lines.join('\n'); output = removeHiddenMenuText(output); return output; } getStyle = function(name = '') { if (name !== null && typeof name === 'object') { return name; } let empty_style = { 'background': null, 'color' : null }; if (!name) { return empty_style; } if (typeof cb.settings[name] !== 'undefined') { name = cb.settings[name]; } if (!name) { return empty_style; } if (name.indexOf('Random') > -1) { return getRandomStyle(name); } return typeof styles[name] !== 'undefined' ? styles[name] : empty_style; }; getRandomStyle = function(name) { let id = name.indexOf('Dark') > -1 ? 'styles_dark' : name.indexOf('Light') > -1 ? 'styles_light' : 'styles'; if (typeof random[id] === 'undefined' || !random[id].length) { random[id] = getObjectValues( styles, id === 'styles_light' ? 'Light' : '', id === 'styles_dark' ? 'Light' : '' ); } let pos = Math.floor(Math.random() * random[id].length); let style = random[id][pos]; // remove style, so it doesn't get repeated random[id].splice(pos, 1); return style; }; getColor = function(name = '') { if (!name) { return '#000000'; } if (typeof cb.settings[name] !== 'undefined') { name = cb.settings[name]; } name = name.toLowerCase(); return typeof colors[name] !== 'undefined' ? colors[name] : '#000000'; }; getIcon = function(name = '') { if (!name) { return ''; } if (typeof cb.settings[name] !== 'undefined') { name = cb.settings[name]; } name = name.toLowerCase(); if (name === 'random thank you') { return getRandomThankYouIcon(); } if (name.indexOf('random') > -1) { return getRandomIcon(); } return typeof icons[name] !== 'undefined' ? icons[name] : ''; }; getRandomThankYouIcon = function() { random_thank_you_icon_number += 1; if (random_thank_you_icon_number > 48 || random_thank_you_icon_number < 10) { random_thank_you_icon_number = 10; } return ':gladyty' + random_thank_you_icon_number; }; getRandomIcon = function() { if (typeof random.icons === 'undefined' || !random.icons.length) { random.icons = getObjectValues(icons); } const pos = Math.floor(Math.random() * random.icons.length); const icon = random.icons[pos]; if (icon.indexOf(':') === 1) { return getRandomIcon(); } // remove icon, so it doesn't get repeated random.icons.splice(pos, 1); return icon; }; function getRandomInt(min, max) { min = Math.ceil(min); max = Math.floor(max) + 1; return Math.floor(Math.random() * (max - min) + min); }; getLovenseIcon = function(icon, style_name) { if (typeof lovense_icon_styles[style_name] === 'undefined' || typeof lovense_icon_styles[style_name][icon] === 'undefined') { return ''; } return lovense_icon_styles[style_name][icon]; }; getSeparator = function(type = '', icon = '', repeat = 40, layout = 'Vertical') { if (type !== '' && typeof cb.settings[type] !== 'undefined') { type = cb.settings[type]; } switch (type) { case 'Icon': return ' ' + icon + ' '; case 'Icons': return (icon + ' ').repeat(repeat / 2).trim() + '\n'; case 'Colon': return ' : '; case 'Dash': return ' - '; case 'Newline': return layout === 'Horizontal' ? '\n' : icon + '\n'; case 'Lush Icon': return ' ' + getIcon('lush') + ' '; default: return ' '; } }; getObjectValues = function(object, include = '', exclude = '') { let values = []; for (let key in object) { if (include && key.indexOf(include) === -1) { continue; } if (exclude && key.indexOf(exclude) > -1) { continue; } values.push(object[key]); } return values; }; getBackgroundColorLight = function(color) { return 'linear-gradient(63.435deg, rgba(' + color + ', 0.25), rgba(' + color + ', 0.05), rgba(' + color + ', 0.25), rgba(' + color + ', 0.05), rgba(' + color + ', 0.25), rgba(' + color + ', 0.05), rgba(' + color + ', 0.25))'; }; getBackgroundColorDark = function(color) { return 'linear-gradient(63.435deg, rgb(' + color + '), rgba(' + color + ', 0.85), rgb(' + color + '), rgba(' + color + ', 0.85), rgb(' + color + '), rgba(' + color + ', 0.85), rgb(' + color + '))'; }; getUserName = function(user) { return user !== null && typeof user === 'object' ? user.user : user; }; getUserGroupByName = function(name) { if (name === '') { return ''; } if (typeof cb.settings[name] !== 'undefined') { name = cb.settings[name]; } for (let key in user_groups) { if (user_groups[key] !== name) { continue; } return key === '0' ? '' : key; } return name === '0' ? '' : name; }; getDuration = function(secs) { if (typeof cb.settings[secs] !== 'undefined') { secs = cb.settings[secs]; } if (secs < 60 || secs % 60) { return secs + 'sec'; } let mins = secs / 60; return mins + 'min'; }; pad = function(str, pad_char, total_length = 0) { if (!total_length) { return str; } const pad_length = total_length - str.toString().length; const repeat = Math.floor(pad_length / pad_char.toString().length); return pad_char.toString().repeat(repeat) + str; }; getTimeOnline = function() { let secs = Math.floor((Date.now() - start_time) / 1000); const hours = Math.floor(secs / (60 * 60)); secs = secs - (hours * 60 * 60); const mins = Math.floor(secs / 60); secs = secs - (mins * 60); return pad(hours, 0, 2) + ':' + pad(mins, 0, 2) + ':' + pad(secs, 0, 2); }; resetSectionLetter = function() { section_letter = 64; }; getNextSectionLetter = function() { section_letter += 1; return String.fromCharCode(section_letter); }; form = { 'createTitle': function(label = '', level = 0, width = 42) { label = label ? label + ' ' : ''; let leading = ''; let trailing = ''; if (level) { let line = '='; let repeat = width; switch (level) { case 3: line = ':'; break; case 2: line = '~'; break; case 1: line = '='; label = label.toUpperCase(); break; } leading = line.repeat(repeat) + ': '; trailing = ' ' + line.repeat(repeat); if (level === 3) { repeat = (repeat - (label.length + 10)) * 2; repeat = Math.max(repeat, 0); leading = repeat ? line.repeat(repeat) + ': ' : ''; trailing = ' ' + line.repeat(10); } if (!label) { leading = ''; } } return { name : 'line' + (++settings_notice_count), label : leading + label + trailing, type : 'choice', choice1 : ':', required: false }; }, 'title': function(label = '') { return form.createTitle(label, 1); }, 'subTitle': function(label = '') { return form.createTitle(label, 2); }, 'subSubTitle': function(label = '') { return form.createTitle(label, 3); }, 'line': function(level = 1, width = 42) { return form.createTitle('', level, width); }, 'notice': function(text = '', label = '') { return { name : 'line' + (++settings_notice_count), label : label ? 'Note: ' + label : 'Note', type : 'choice', choice1 : text, required: false }; }, 'userGroups': function(name = '', label = '', defaultValue = '0') { const option = { name : name, label : label ? label : 'Send Message to', type : 'choice', defaultValue: user_groups[defaultValue], required : false }; count = 0; for (let group_name in user_groups) { option['choice' + (++count)] = user_groups[group_name]; } return option; }, 'userGroupsPlusSelf': function(name = '', self_name = 'Tipper', label = '', defaultValue = '') { let value = self_name; if (defaultValue) { value = typeof user_groups[defaultValue] !== 'undefined' ? user_groups[defaultValue] : defaultValue; } const option = { name : name, label : label ? label : 'Send Message to', type : 'choice', defaultValue: value, choice1 : self_name, choice2 : self_name + ' & Room Owner', choice3 : self_name + ' & Room Owner & Moderators', required : false }; count = 3; for (let group_name in user_groups) { option['choice' + (++count)] = user_groups[group_name]; } return option; }, 'icons': function(name = '', label = '', defaultValue = 'Diamond') { const option = { name : name, label : label ? label : 'Icon', type : 'choice', defaultValue: defaultValue, required : false, choice1 : '- None -', choice2 : '- Random -', }; count = 2; for (let name in icons) { option['choice' + (++count)] = name.toTitleCase(); } return option; }, 'lovenseStyles': function(name, label = '', defaultValue = '') { const option = { name : name, label : label ? label : 'Lovense Icon Style', type : 'choice', defaultValue: defaultValue, required : false, choice1 : '- None -', }; count = 1; for (let name in lovense_icon_styles) { option['choice' + (++count)] = name.toTitleCase(); } return option; }, 'styles': function(name = '', label = '', defaultValue = '- Random Light -') { const option = { name : name, label : label ? label : 'Style', type : 'choice', defaultValue: defaultValue, required : false, choice1 : '- None -', choice2 : '- Random -', choice3 : '- Random Dark -', choice4 : '- Random Light -', }; count = 4; for (name in styles) { option['choice' + (++count)] = name.toTitleCase(); } return option; }, 'colors': function(name = '', label = '', defaultValue = 'Black') { const option = { name : name, label : label ? label : 'Color', type : 'choice', defaultValue: defaultValue, required : false, }; count = 0; for (name in colors) { option['choice' + (++count)] = name.toTitleCase(); } return option; } }; init(); }
© Copyright Chaturbate 2011- 2024. All Rights Reserved.