Apps Home
|
Create an App
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Author:
aspirante001
Description
Source Code
Launch App
Current Users
Created by:
Aspirante001
/** Name: Dorothy's Tip Goals v2 Author: butter_my_toast Created 02/19/2019 **/ //** Enable for ESLINT syntax check, Disable for CB compile //var cb = ''; //var cbjs = ''; //** Enable Show1 or Show2 depending on app version since the panel background upload image names are different for each var appVersion = 'Show1'; //var appVersion = 'Show2'; var dummycounter = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56' ]; var backgroundArray = { menu: ['Cube Wave', 'Hearts', 'Blue Floral', 'Aquarium', 'Snakeskin', 'Pastels', 'Clouds', 'Lava Lamp', 'Light Blue', 'Moon', 'My Custom Panel', 'Purple Haze', 'Blue Bars', 'Valentines Pink Bars', 'Valentines 2 Hearts', 'Green and Blue Bars', 'Pink and Blue Bars', 'Green and Green Bars', 'Aqua and Yellow Bars', 'Purple and Pink Bars', 'Aqua and Pink Bars', 'Pink and Pink Bars', 'Yellow and Yellow Bars', 'Christmas - Silver snowflakes', 'Rainbow in the Clouds', 'Christmas Lights', 'Christmas - Green background', 'Christmas - Blue and Silver', 'Halloween - spooky pumpkins', 'Halloween - bouncing pumpkin', 'Halloween - Red sky lightning', 'Halloween - orange sky bats', 'Halloween - blue sky bats', 'Halloween - blue with ghosts', 'Christmas - BW Snowflakes', 'Christmas - Blue Snowflakes', 'Christmas - Snowflake border', 'Christmas - Red with snow', 'Christmas - Red Santa and snowman', 'Christmas - Wrapping Paper', 'Christmas - Classic', 'Pastel Aqua Stars', 'Black Leather Texture', 'St. Patricks Day 1', 'St. Patricks Day 2', 'St. Patricks Day 3', 'Flowers Blue', 'Flowers Cream and Rose', 'Lily Pads', 'Flowers Green and White', 'Green Leaves Pattern', 'Mauve Leaf Pattern', 'White Rose', 'Green Pattern', 'Dark Blue-Green Watercolor', 'Aqua Watercolor', 'Green Diamond Pattern' ], command: ['cubewave', 'hearts', 'bluefloral', 'aquarium', 'snakeskin', 'pastels', 'clouds', 'lavalamp', 'lightblue', 'moon', 'custom', 'purplehaze', 'bluegradient', 'valentines1', 'valentines2', 'greenblue', 'pinkblue', 'greengreen', 'aquayellow', 'purplepink', 'aquapink', 'pinkpink', 'yellowyellow', 'christmas1silversnowflakes', 'rainbowclouds', 'christmas2lights', 'christmas3green', 'christmas4blue', 'halloween1', 'halloween2', 'halloween3', 'halloween4', 'halloween5', 'halloween7', 'christmas4bw', 'christmas5bluesnowflakes', 'christmas6snowflakesborder', 'christmas7red1', 'christmas8red2', 'christmas9wrap', 'christmas10classic', 'pastelaqua', 'blackleather', 'stpatrick1', 'stpatrick2', 'stpatrick3', 'flowersblue', 'flowerscreamrose', 'lilypads', 'flowersgreenwhite', 'greenleaves', 'mauveleaf', 'whiterose', 'greenpattern', 'bluegreenwatercolor', 'aquawatercolor', 'greendiamond' ], devfile: ['c7677af8-a834-41dd-b85a-84504f9a1704','add', 'add', '9923755e-8ef8-43e7-bf9d-5523384e889d', 'add', 'add', 'ed0186a2-0c1c-4ec2-a657-68c7904e8235', 'c9a669c2-1de9-4368-9ac0-5fdf5eb7f31d', 'add', 'add', 'NA', 'add ', 'add', 'add', 'add', 'add', 'add', 'add ', 'add', 'add', 'add', 'add', 'add', 'add', '1ba66b11-d5b8-4fc2-933d-d6ca4ca4e808', 'add', 'add', 'add', 'add', 'add', 'add', 'add', 'add', 'add', 'add', 'add', 'add', 'add', 'add', 'add', 'add', 'add', 'add', 'cd1d941d-0a4d-4bc1-975c-32a7073f951b', 'add', '6967fc13-202c-49ff-8f15-6b92812c87ff', 'cd14e0dc-20d1-438a-a6f6-101cc8278d4f', 'add', 'c7712dc0-5629-4b67-9a22-2d7835835a75', 'add', 'add', 'add', 'add', 'add', 'add', 'add', 'add' ], livefile: ['5c761833-004d-4ede-a0ec-2af1ab01f355','56c61a44-8f7e-4fa7-aec3-1c5014901668', 'db3b2d44-b1a4-4e75-857c-1655a4289c37', '769ab1c7-cf54-440a-b068-3aa63f2d4e2d', 'd078bed1-0d97-4835-91aa-7e0afa8c5351', 'cf9c4af4-2fe3-45a7-bbad-f9668773f9b7', '51c32ede-98da-4ef7-be05-f3af87f8a161', '124cf05b-2e6a-4c5b-81f5-36dd91e49dfa', '294562e6-ba51-4649-a04c-e5b0ee3d811c', 'd95aad54-5951-473d-8fc5-ce70c5ea04d7', 'NA', 'ddd7914a-38ff-4a98-82e3-5a1dcaf8fa1f', '79c00c7a-50ec-4851-bff6-dc755fc7c965', 'f7dae9fc-abaa-4e98-a404-768f6b8e7cde', 'b3843415-a843-4d32-b6ff-e123eea66402', '2b3694b7-b961-4f7a-9ea9-e42ad284c909', '08e1c60a-9f32-4d6d-a0a2-15c75696d444', '923027b6-4950-44fb-9a65-ddd429e95e73', 'e3bd1bb5-f760-42b1-8e15-7c80a50407b8', '70d429b5-ebe3-44c5-a46d-394524a7347b', 'daeaf77a-3c60-47f4-ab96-0ae005f78bb8', '70d429b5-ebe3-44c5-a46d-394524a7347b', '92e84508-825b-4edf-8a85-2c7d15689644', '3cbbc8d2-0514-4b05-ba51-824397de3309', '55c72eda-afd0-4a85-af30-50d8651cacf3', '3bec7986-59c0-4504-9d8c-4f72a9ecc00d', '550e3710-51e1-445a-a106-e52153ceb817', 'db5b693f-2dc8-4bcd-a194-19bf6840630c', '28b75dc0-bc10-4b77-afeb-4cb6adcbb93d', 'de6e1729-f282-4b45-8af2-42155ed038dd', '01badbca-4397-40f4-93e8-43affff87f87', '51395c5f-3f74-40ed-adfe-742b4d5fd1e0', '1f944e8a-7217-4ac1-860a-4f5a777fb93c', 'ac5ad60c-96ec-46f9-8618-823131646bc7', '3cbbc8d2-0514-4b05-ba51-824397de3309', 'ca42ee81-bfc5-41a8-8ad5-80f9da3437aa', '30cd80e2-9c14-4eff-95c1-05030108930f', '708849a4-33d8-4981-931e-eae9bf41b632', '83ebdba9-11d6-4c9f-8758-0428367154e2', 'a621262e-bf0a-4fbb-9fd4-30b62aa83347', '7a2b18f6-29ae-489c-b34f-8c924eafc4c9', 'f308f44f-a1bc-4287-8188-93697e65ece4', 'd74951af-728c-429b-a583-210b3bae155d', '27c482bd-3fa5-46ba-a5c2-62ff401986d4', 'c032c396-98aa-4414-8ad4-2d21e7624116', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 'd3f0a182-f62d-4785-82b8-ae19d94c776f', 'bf6d3cbf-fa0a-4830-a999-ffb7401a5a03', '966fc403-624c-41f2-b36d-1c4942745ece', '5311a6d5-d6da-46e3-8173-65784c7599ed', '70a13165-ec26-41a6-9bc0-af1ef856891c', '5933a5a3-b369-4c79-8fab-71a6a13bf767', '94e8818f-3028-44df-979f-e960e40a8d67', '8c1c95af-aee2-4891-ab15-67e14275456b', '02cf4693-08a0-4ad9-b058-d8f6d653d71e', '77d3ab76-8b0c-4313-9371-23d03b1cd953', '11bdd6dd-7c1f-4841-9e3a-9dbe6bf904c6' ], livefile2: [''] }; var backgroundArrayCustom = { menu: ['Dorothy - Testbed', 'Liv and Drew', 'Batmansuperhero' ], command: ['dorothy', 'livanddrew', 'batmansuperhero' ], devfile: ['e8692639-7f53-4ce4-8eb6-7e33de58f0e0', 'add', 'add' ], livefile: ['NA', '51864982-fa61-466f-9de6-367461031eb9', '357665d8-b76a-4fa0-a49c-ac85c33982ad' ], livefile2: ['NA', '3dfe588d-6b3b-4059-96b2-c5b1da9ecb9b', 'bfdb4283-7b9f-4046-ab29-1191b5190e08' ] }; var botPanel = false; var t01brightrainbow = 'linear-gradient(to right, #ff6767, #ffdb9a, #ffff9d, #5fd85f, #9f9fff, #ff9bff)'; var t02pastelrainbow = 'linear-gradient(to right, #ff9a9a, #ffe4b4, #ffffb4, #bfd9bf, #add8e6, #e0d6f4)'; var t03valentines = 'linear-gradient(to right bottom, #ff7373, #ffe1f1)'; var t04christmas = 'linear-gradient(to right bottom, #6bdb6b, #ff9a9a)'; var t05halloween = 'linear-gradient(to right bottom, #ffba67, #ffffb4)'; var t06blue = 'linear-gradient(to right bottom, #a9c4f5, #d4ebf2)'; var t07green = 'linear-gradient(to right bottom, #9fc69f, #cfe3cf)'; var t08pink = 'linear-gradient(to right bottom, #ffb6da, #ffe9ec)'; var t09purple = 'linear-gradient(to right bottom, #c1adea, #dfd5f5)'; var t10blackgray = 'linear-gradient(to right bottom, #c6c6c6, #ececec)'; var t11sunset = 'linear-gradient(to right, #9489c2, #c600fb, #ffa200, #c600fb, #9489c2)'; var t12abv = 'linear-gradient(to right bottom, #00e0ff, #c600fb, #9489c2)'; var t13rwb = 'linear-gradient(to right bottom, #ff0000, #ffffff, #0027c1)'; var t14stpat = 'linear-gradient(to right bottom, #0e7312, #c0e6c3, #0e7312)'; var themeArray = { name: ['None', 'Custom', 'Bright Rainbow', 'Pastel Rainbow', 'Valentines', 'Christmas', 'Halloween', 'Shades of Blue', 'Shades of Green', 'Shades of Pink', 'Shades of Purple', 'Black and Gray', 'Sunset', 'Aqua/Blue/Violet', 'Red/White/Blue', 'St Patrick\'s Day' ], shortcut: ['none', 'custom', 'brightrainbow', 'pastelrainbow', 'valentines', 'christmas', 'halloween', 'shadesblue', 'shadesgreen', 'shadespink', 'shadespurple', 'blackgray', 'sunset', 'aquablue', 'redwhiteblue', 'stpat' ], colorID: ['none', 'custom', t01brightrainbow, t02pastelrainbow, t03valentines, t04christmas, t05halloween, t06blue, t07green, t08pink, t09purple, t10blackgray, t11sunset, t12abv, t13rwb, t14stpat ], textcolor: ['none', 'custom', '#00008b', '#00008b', '#c7006b', '#ffffff', '#000000', '#00008b', '#006400', '#d00068', '#663399', '#000000', '#000000', '#d4ebf2', '#000000', '#024604' ]}; var textColorArray = { dispname: ['White/No Color', 'Black', 'Dark Grey', 'Dark Red', 'Dark Orange', 'Dark Green', 'Dark Aqua', 'Dark Blue', 'Dark Purple', 'Dark Pink', 'Dark Gold', 'Dark Teal', 'Dark Brown', 'Dark Bronze', 'Dark Periwinkle', 'Dark Fuschia', 'Dark Lime', 'Dark Plum' ], name: ['white', 'black', 'darkgrey', 'darkred', 'darkorange', 'darkgreen', 'darkaqua', 'darkblue', 'darkpurple', 'darkpink', 'darkgold', 'darkteal', 'darkbrown', 'darkbronze', 'darkperiwinkle', 'darkfuschia', 'darklime', 'darkplum' ], colorID: ['#FFFFFF', '#000000', '#737373', '#cc0000', '#e77400', '#006600', '#006767', '#0629AC', '#3d003d', '#FF6680', '#998100', '#003f1f', '#582c00', '#a56728', '#155bd7', '#d6155c', '#6b790c', '#7f13bf' ]}; var bgColorArray = { dispname: ['White/No Color', 'Light Yellow', 'Light Blue', 'Light Pink', 'Light Red', 'Light Green', 'Light Purple', 'Light Orange', 'Light Grey', 'Light Aqua', 'Light Teal', 'Cream', 'Light Bronze', 'Light Periwinkle', 'Light Fuschia', 'Light Lime', 'Light Plum'], name: ['white', 'lightyellow', 'lightblue', 'lightpink', 'lightred', 'lightgreen', 'lightpurple', 'lightorange', 'lightgrey', 'lightaqua', 'lightteal', 'cream', 'lightbronze', 'lightperiwinkle', 'lightfuschia', 'lightlime', 'lightplum' ], colorID: ['#FFFFFF', '#ffff94', '#d1eaee', '#FFE6EA', '#ff9a9a', '#94e594', '#f2cdff', '#ffd9b3', '#e6e6e6', '#adeaea', '#d7fbee', '#f9f6ed', '#ebccad', '#d7e4fb', '#fbd7e4', '#ecf6a7', '#e3c0f9' ]}; cb.settings_choices = [ {name: 'intro', label: '******************* INTRODUCTION ********************* Latest Update: April 8, 2021 (version 2.1) ********************************************************* Welcome to Dorothy\'s Tip Goals App. You can see the full list of commands for the App by typing "/goalhelp" in the chat (no quotes), and then also see more detailed help by section. It is expected that you would be using an Ultrabot such as Dorothy\'s Ultra Fembot alongside this for features such as Chat Control and Tipper Count/Leader features. Please DM us on twitter @thechelsea2950 if you have questions. Thank you! - butter_my_toast and chelsea2950', type: 'choice',required: false}, {name: 'intro2', label: '*** NOTICE! *** Version 2.0 was a significant change to the App, bringing it up to date with the current features in the Progressive Goals portion of Dorothy\'s Ultra App. Please review the features and your current settings!', type: 'choice',required: false}, // *** General Settings {name: 'section1', label: ' ------------------------------------------------------------------------------------- SECTION 1: SETUP -------------------------------------------------------------------------------------- ', type: 'choice',required: false}, {name: 'progressiveRoomSubjectSfx', label: '1A. Room Title Text -- Enter the show description text and/or hashtags you would like shown in the room title', type: 'str',required: false, minLength: 1, maxLength: 200, defaultValue: 'Sex Show at Final Goal #couple #goals'}, {name: 'progressiveAutoNext', label: '1B. Next Goal Selection -- There are three ways the app can be configured for controlling what happens when you finish a goal: (1) automatically start next goal (2) wait for the broadcaster or a moderator to start the next goal with the "/next" command, or (3) allow the broadcaster or a moderator to select the next goal from your goal list. Note that with options (2) and (3), tips that exceed the current goal are not counted toward the next goal. Tips start counting again once the new goal is started. With auto-start, the excess tip amount is rolled over into the next goal. When set to "Select next goal from list", the recurring notice for remaining goals will be disabled, and the app will never automatically show "All goals complete", you are always prompted to select the next.', type: 'choice', choice1: 'Auto-start next', choice2: 'Manually start next', choice3: 'Select next goal from list', defaultValue: 'Auto-start next'}, {name: 'progressiveUpDown', label: '1C. Count Up or Count Down -- Choose if you want to count up from zero to each goal amount, or count down from the goal amount to zero', type: 'choice', choice1: 'Count Up To Goal', choice2: 'Count Down To Zero', defaultValue: 'Count Up To Goal'}, // *** Goals {name: 'section2', label: '-------------------------------------------------------------------------------------- SECTION 2: GOALS -------------------------------------------------------------------------------------- You can set up a single goal or multiple goals. Each goal amount is specific to that goal, it is not the cumulative total. You can set a goal amount to be negative (with a dash in front) to keep it in your settings for later but not use it for this show.', type: 'choice',required: false}, {name: 'progressiveGoalDescription1', label: 'Goal #1 Description', type: 'str',required: true, minLength: 1, maxLength: 100}, {name: 'progressiveGoalAmount1', label: 'Goal #1 Amount', type: 'int',required: true, minValue: -99999, maxValue: 99999}, {name: 'progressiveGoalDescription2', label: 'Goal #2 Description', type: 'str',required: false, minLength: 1, maxLength: 100}, {name: 'progressiveGoalAmount2', label: 'Goal #2 Amount', type: 'int',required: false, minValue: -99999, maxValue: 99999}, {name: 'progressiveGoalDescription3', label: 'Goal #3 Description', type: 'str',required: false, minLength: 1, maxLength: 100}, {name: 'progressiveGoalAmount3', label: 'Goal #3 Amount', type: 'int',required: false, minValue: -99999, maxValue: 99999}, {name: 'progressiveGoalDescription4', label: 'Goal #4 Description', type: 'str',required: false, minLength: 1, maxLength: 100}, {name: 'progressiveGoalAmount4', label: 'Goal #4 Amount', type: 'int',required: false, minValue: -99999, maxValue: 99999}, {name: 'progressiveGoalDescription5', label: 'Goal #5 Description', type: 'str',required: false, minLength: 1, maxLength: 100}, {name: 'progressiveGoalAmount5', label: 'Goal #5 Amount', type: 'int',required: false, minValue: -99999, maxValue: 99999}, {name: 'progressiveGoalDescription6', label: 'Goal #6 Description', type: 'str',required: false, minLength: 1, maxLength: 100}, {name: 'progressiveGoalAmount6', label: 'Goal #6 Amount', type: 'int',required: false, minValue: -99999, maxValue: 99999}, {name: 'progressiveGoalDescription7', label: 'Goal #7 Description', type: 'str',required: false, minLength: 1, maxLength: 100}, {name: 'progressiveGoalAmount7', label: 'Goal #7 Amount', type: 'int',required: false, minValue: -99999, maxValue: 99999}, {name: 'progressiveGoalDescription8', label: 'Goal #8 Description', type: 'str',required: false, minLength: 1, maxLength: 100}, {name: 'progressiveGoalAmount8', label: 'Goal #8 Amount', type: 'int',required: false, minValue: -99999, maxValue: 99999}, {name: 'progressiveGoalDescription9', label: 'Goal #9 Description', type: 'str',required: false, minLength: 1, maxLength: 100}, {name: 'progressiveGoalAmount9', label: 'Goal #9 Amount', type: 'int',required: false, minValue: -99999, maxValue: 99999}, {name: 'progressiveGoalDescription10', label: 'Goal #10 Description', type: 'str',required: false, minLength: 1, maxLength: 100}, {name: 'progressiveGoalAmount10', label: 'Goal #10 Amount', type: 'int',required: false, minValue: -99999, maxValue: 99999}, {name: 'progressiveGoalDescription11', label: 'Goal #11 Description', type: 'str',required: false, minLength: 1, maxLength: 100}, {name: 'progressiveGoalAmount11', label: 'Goal #11 Amount', type: 'int',required: false, minValue: -99999, maxValue: 99999}, {name: 'progressiveGoalDescription12', label: 'Goal #12 Description', type: 'str',required: false, minLength: 1, maxLength: 100}, {name: 'progressiveGoalAmount12', label: 'Goal #12 Amount', type: 'int',required: false, minValue: -99999, maxValue: 99999}, {name: 'progressiveGoalDescription13', label: 'Goal #13 Description', type: 'str',required: false, minLength: 1, maxLength: 100}, {name: 'progressiveGoalAmount13', label: 'Goal #13 Amount', type: 'int',required: false, minValue: -99999, maxValue: 99999}, {name: 'progressiveGoalDescription14', label: 'Goal #14 Description', type: 'str',required: false, minLength: 1, maxLength: 100}, {name: 'progressiveGoalAmount14', label: 'Goal #14 Amount', type: 'int',required: false, minValue: -99999, maxValue: 99999}, {name: 'progressiveGoalDescription15', label: 'Goal #15 Description', type: 'str',required: false, minLength: 1, maxLength: 100}, {name: 'progressiveGoalAmount15', label: 'Goal #15 Amount', type: 'int',required: false, minValue: -99999, maxValue: 99999}, {name: 'progressiveGoalDescription16', label: 'Goal #16 Description', type: 'str',required: false, minLength: 1, maxLength: 100}, {name: 'progressiveGoalAmount16', label: 'Goal #16 Amount', type: 'int',required: false, minValue: -99999, maxValue: 99999}, {name: 'progressiveGoalDescription17', label: 'Goal #17 Description', type: 'str',required: false, minLength: 1, maxLength: 100}, {name: 'progressiveGoalAmount17', label: 'Goal #17 Amount', type: 'int',required: false, minValue: -99999, maxValue: 99999}, {name: 'progressiveGoalDescription18', label: 'Goal #18 Description', type: 'str',required: false, minLength: 1, maxLength: 100}, {name: 'progressiveGoalAmount18', label: 'Goal #18 Amount', type: 'int',required: false, minValue: -99999, maxValue: 99999}, {name: 'progressiveGoalDescription19', label: 'Goal #19 Description', type: 'str',required: false, minLength: 1, maxLength: 100}, {name: 'progressiveGoalAmount19', label: 'Goal #19 Amount', type: 'int',required: false, minValue: -99999, maxValue: 99999}, {name: 'progressiveGoalDescription20', label: 'Goal #20 Description', type: 'str',required: false, minLength: 1, maxLength: 100}, {name: 'progressiveGoalAmount20', label: 'Goal #20 Amount', type: 'int',required: false, minValue: -99999, maxValue: 99999}, // *** Personalization {name: 'section3', label: '-------------------------------------------------------------------------------------- SECTION 3: PERSONALIZATION -------------------------------------------------------------------------------------- ', type: 'choice',required: false}, {name: 'bctext', label: '3A. Your Display Name -- Replace the general term "broadcaster" and in some cases the room name with the name of your choosing (the name you would like to be called, couples name, etc) wherever it appears in chat notices. Leave blank to just use "The Broadcaster".', type: 'str',required: false, minLength: 1, maxLength: 50}, {name: 'enableEntryMessage', label: '3B. Welcome Notice? -- Display a notification to users when they enter?', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'Yes'}, {name: 'entryMessage', label: '3C. Welcome Text -- Enter the message to display. The substitution text strings {username} and {n} can be used within your welcome text to have the username of the person joining the room show in the welcome message, or make a line break. Just make sure there is a space on either side of the identifier so that it is recognized. Leave this field blank if you\'ve configured a general welcome message in your Ultrabot or another bot', type: 'str',required: false, minLength: 1, maxLength: 1000, defaultValue: 'Welcome {username} to my room! Please enjoy the show and take part in helping to reach the goal.'}, {name: 'modLevel', label: '3D. Moderator Trust Level -- This will control how much command authority is granted to moderators. The same moderator level is applied to all moderators (not user specific). There are 3 levels - Basic, Standard, and Advanced. "Standard" covers most of what mods are normally able to do and will be the default. Basic gives less access which is ideal when you are newer and may not have trusted mods yet. "Advanced" gives them mostly the same abilities to use commands as a broadcaster. See the App description page or type the command /modlevels in the chat for a full listing of the Access for each mod level.', type: 'choice', choice1: 'Basic', choice2: 'Standard', choice3: 'Advanced', defaultValue: 'Standard'}, {name: 'textWrapLength', label: '3E. Max Line Length -- Set the number of characters at which to wrap a long line of text to the next line, used for welcome message, goal summary, help text, etc. Default value is 80 as that typically fits the width of the border for recurring notices, and must be at least 25 or set to zero to disable automatic line wrapping. Values from 1-24 will default to 25', type: 'int',minValue: 0,maxValue: 120,defaultValue: 80}, {name: 'section3a', label: '--- ROOM TITLE --- ', type: 'choice',required: false}, {name: 'roomTitleFormat', label: '3F. Room Title Format -- What information should be displayed in the room title? Setting to "All" will display all three types of info: the user entered Room Title text from setting "1A" above, the predefined text about the current goal, and the predefined text about the next goal. Setting to "Room Title and Current Goal" will only display the Goal Title and the current goal info. Setting to "Room Title Only" will exclude the pre-defined current goal and next goal information and only display the user-entered Room Title.', type: 'choice', choice1: 'All', choice2: 'Room Title and Current Goal', choice3: 'Room Title Only', defaultValue: 'All'}, {name: 'roomTitleTextPosn', label: '3G. Room Title Text Position -- Show the Room Title Text before or after the current goal and next goal information (if used)', type: 'choice', choice1: 'Before', choice2: 'After', defaultValue: 'After'}, {name: 'roomTitleRemTokens', label: '3H. Room Title Includes Tokens left to Goal? -- Should the number of tokens left to a goal be displayed in the room title? This is not recommended since it will then post a chat message about the updated room title after every tip, but can be enabled if you really want this to show in the title. You can put the count at the very beginning or very end of the room title. Note that if you put it at the beginning, it will show in the preview of your room on the thumbnails page', type: 'choice', choice1: 'No', choice2: 'Yes, at beginning', choice3: 'Yes, at end', defaultValue: 'No'}, {name: 'section3b', label: '--- GOAL NOTICE --- ', type: 'choice',required: false}, {name: 'progressiveGoalNoticeInterval', label: '3J. Goal Notice Interval -- Time interval for displaying the Goals Notice in the chat, in minutes. Decimals are ok as long as they are greater than 1. For example, 1.5 = "One minute and 30 second" intervals. Set to 0 to disable the notice.',required: false,type: 'str',defaultValue: 4.1}, {name: 'progressiveIncludeGoals', label: '3K. Goal Notice Includes Goal List? -- Choose if you want to include a list of the remaining goals in the recurring Goal Notice. This will be disabled automatically if the next goal mode is set to "Select next goal from list"', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'No'}, {name: 'colorTheme', label: '3L. Goal Notice Color Theme -- This sets the background highlighting in the recurring notices. When choosing "custom", enter your chosen colors below in settings 3M1-3M5.', type: 'choice', choice1: themeArray.name[0], choice2: themeArray.name[1], choice3: themeArray.name[2], choice4: themeArray.name[3], choice5: themeArray.name[4], choice6: themeArray.name[5], choice7: themeArray.name[6], choice8: themeArray.name[7], choice9: themeArray.name[8], choice10: themeArray.name[9], choice11: themeArray.name[10], choice12: themeArray.name[11], choice13: themeArray.name[12], choice14: themeArray.name[13], choice15: themeArray.name[14], choice16: themeArray.name[15], defaultValue: themeArray.name[7]}, {name: 'colorThemeCustBg1', label: '3M1. Goal Notice Custom Color 1 - If you picked "custom" color theme above in setting "3L", enter the hex color code for background color 1 ("#" prefix plus the 6 character hex color codes, such #ffffff)',type: 'str',minLength: 1,maxLength: 7,required: false}, {name: 'colorThemeCustBg2', label: '3M2. Goal Notice Custom Color 2 - If you picked "custom" color theme above in setting "3L", enter the hex color code for background color 2, it will default to white (#ffffff) if none is chosen as two colors are required',type: 'str',minLength: 1,maxLength: 7,required: false}, {name: 'colorThemeCustBg3', label: '3M3. Goal Notice Custom Color 3 - If you picked "custom" color theme above in setting "3L", enter the hex color code for background color 3 (optional)',type: 'str',minLength: 1,maxLength: 7,required: false}, {name: 'colorsGradientDirection', label: '3M4. Goal Notice Custom Color Fade Direction -- You can also choose the direction of the color fading as it blends from one color to another. Note that this setting is only used with the custom color settings. If a pre-defined color theme is used above, the gradient direction is unique to the theme and this setting will be ignored', type: 'choice', choice1: 'None - Solid Color', choice2: 'Linear, left to right', choice3: 'Linear, top to bottom', choice4: 'Linear, diagonally', defaultValue: 'Linear, diagonally'}, {name: 'colorThemeCustText', label: '3M5. Goal Notice Custom Text Color - If you picked "custom" color theme above in setting "3L", enter the hex color code for text - it will default to white if none is chosen', type: 'str',minLength: 1,maxLength: 7,required: false}, {name: 'noticeSepStyle', label: '3N1. Goal Notice Border Style -- This controls how the top and bottom border of several of the recurring notices are displayed. You can choose from the defined options here, or use the below setting for "3N2" to define your own emoji or other character. Depending on the type you choose, the spacing of the border will be different, so be sure to select the matching type here for the emoji or character you set below.', type: 'choice', choice1: 'No Border', choice2: 'Light Dashed Line', choice3: 'Heavy Dashed Line', choice4: 'Custom Emoji Below', choice5: 'Custom Unicode Character Below', defaultValue: 'Light Dashed Line'}, {name: 'separatorEmoji', label: '3N2. Goal Notice Border Custom Character -- For an emoji or unicode character, paste the actual emoji/image here, not the unicode value code (not "\u2580", for example). Note that most unicode characters have the benfit of being the same color as your text. The borders are currently used for leaderboard, media info, room rules, dice game, and icon tip notices. Do NOT use a CB icon here, if you do, it will default to "Heavy Dashed Line". You can use the command /setbrdsep to update the emoji separator during your show and play around with them to find one that has the color and spacing you are looking for.', type: 'str',minLength: 0,maxLength: 2,required: false}, {name: 'section3c', label: '--- DRAW PANEL --- ', type: 'choice',required: false}, {name: 'panelBackground', label: '3P. Draw Panel Background Graphic -- Which background panel type would you like to display? Note you cannot use the "My Custom Panel" background unless they are created for your room, and it will use the default if they are selected when you do not haev one', type: 'choice', choice1: 'default - no image', choice2: backgroundArray.menu[0], choice3: backgroundArray.menu[1], choice4: backgroundArray.menu[2], choice5: backgroundArray.menu[3], choice6: backgroundArray.menu[4], choice7: backgroundArray.menu[5], choice8: backgroundArray.menu[6], choice9: backgroundArray.menu[7], choice10: backgroundArray.menu[8], choice11: backgroundArray.menu[9], choice12: backgroundArray.menu[10], choice13: backgroundArray.menu[11], choice14: backgroundArray.menu[12], choice15: backgroundArray.menu[13], choice16: backgroundArray.menu[14], choice17: backgroundArray.menu[15], choice18: backgroundArray.menu[16], choice19: backgroundArray.menu[17], choice20: backgroundArray.menu[18], choice21: backgroundArray.menu[19], choice22: backgroundArray.menu[20], choice23: backgroundArray.menu[21], choice24: backgroundArray.menu[22], choice25: backgroundArray.menu[23], choice26: backgroundArray.menu[24], choice27: backgroundArray.menu[25], choice28: backgroundArray.menu[26], choice29: backgroundArray.menu[27], choice30: backgroundArray.menu[28], choice31: backgroundArray.menu[29], choice32: backgroundArray.menu[30], choice33: backgroundArray.menu[31], choice34: backgroundArray.menu[32], choice35: backgroundArray.menu[33], choice36: backgroundArray.menu[34], choice37: backgroundArray.menu[35], choice38: backgroundArray.menu[36], choice39: backgroundArray.menu[37], choice40: backgroundArray.menu[38], choice41: backgroundArray.menu[39], choice42: backgroundArray.menu[40], choice43: backgroundArray.menu[41], choice44: backgroundArray.menu[42], choice45: backgroundArray.menu[43], choice46: backgroundArray.menu[44], choice47: backgroundArray.menu[45], choice48: backgroundArray.menu[46], choice49: backgroundArray.menu[47], choice50: backgroundArray.menu[48], choice51: backgroundArray.menu[49], choice52: backgroundArray.menu[50], choice53: backgroundArray.menu[51], choice54: backgroundArray.menu[52], choice55: backgroundArray.menu[53], choice56: backgroundArray.menu[54], choice57: backgroundArray.menu[55], choice58: backgroundArray.menu[56], choice59: backgroundArray.menu[57], choice60: backgroundArray.menu[58], choice61: backgroundArray.menu[59], choice62: backgroundArray.menu[60], choice63: backgroundArray.menu[61], defaultValue: backgroundArray.menu[0]}, {name: 'panelTextColor', label: '3Q1. Draw Panel Text Color -- Text color for the panel text',type: 'choice',choice1: 'White/No Color',choice2: 'Black',choice3: 'Dark Grey',choice4: 'Dark Red',choice5: 'Dark Orange',choice6: 'Dark Green',choice7: 'Dark Aqua',choice8: 'Dark Blue',choice9: 'Dark Purple',choice10: 'Dark Pink',choice11: 'Dark Gold',choice12: 'Dark Teal',choice13: 'Dark Brown',choice14: 'Dark Bronze',choice15: 'Dark Periwinkle',choice16: 'Dark Fuschia',choice17: 'Dark Lime',choice18: 'Dark Plum',choice19: 'Custom',defaultValue: 'Dark Blue'}, {name: 'panelCustomTextColor', label: '3Q2. Draw Panel Text Custom Color -- If you picked a custom text color in the previous setting, enter the hex color (6 character hex color codes including the # prefix, such as #FFFFFF):', type: 'str', minLength: 1, maxLength: 7, required: false}, {name: 'showTotals', label: '3R. Draw Panel Displays Total Tips for the Show (on bottom line)?', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'Yes'}, {name: 'section3d', label: '--- OTHER APPS --- ', type: 'choice',required: false}, {name: 'usingFembot', label: '3S. Are you using Dorothys Ultra Fembot or Easy Fembot alongside this App? If so, setting this to "Yes" will prevent both app and bot from displaying messages twice where commands are common to both, such as the emoji and custom characters list', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'No'} ]; // *********************************** Variables and Arrays ************************************** var initialize = 0; var BC = cb.room_slug; var finalGoalMet = false; var currentGoalMet = false; var noAppPanelText1 = ' '; var noAppPanelText2 = ' '; var noAppPanelText3 = ' '; var highestTip = 0; var highestTipper = 'None'; var mostRecentTip = 0; var mostRecentTipper = 'None'; var fontSize = 12; var bcText = ''; var wrapMaxLength = cb.settings.textWrapLength; var botName = 'Tip Goals App: '; var borderCharSpacing = ''; var borderChar = cb.settings.separatorEmoji; var modLevel = cb.settings.modLevel; var backgroundImage = ''; var currentPanel = ''; var borderWelcomeTop = ''; var borderWelcomeBottom = ''; var borderNoticeTop = ''; var borderNoticeBottom = ''; var borderGoalCompleteTop = ''; var borderGoalCompleteBottom = ''; var textColor = 'black'; var appNoticeColor = '#f4d599'; var appErrorColor = '#f4c1bc'; var colorTheme = cb.settings.colorTheme; var leftjust1 = 99; var leftjust2 = 99; var leftjust3 = 99; var topjust1 = 99; var topjust2 = 99; var topjust3 = 99; var themeWarning = false; var themeWarning2 = false; var themeWarning3 = false; var themeWarning4 = false; var themeWarning5 = false; var goalSubjectText = cb.settings.progressiveRoomSubjectSfx; var roomTitleTextPosn = cb.settings.roomTitleTextPosn; var roomTitleFormat = cb.settings.roomTitleFormat; var progressiveAutoNext = cb.settings.progressiveAutoNext; var currentGoal = 1; var currentGoalTips = 0; var currentGoalTotal = 0; var currentSessionTotal = 0; var currentGoalDesc = ''; var currentAppTotalGoal = 0; var progGoalBgColor = ''; var progGoalTextColor = ''; var progGoalNoticesTxtColor = ''; var progGoalNoticesBgColor = ''; var totalProgGoals = 0; var progGoalNoticeInt = 0; var savedProgGoals = false; var savedCurrentGoalTips = 0; var pgSave_finalGoalMet = false; var pgSave_currentGoalTips = 0; var pgSave_currentGoal = 0; var pgSave_currentGoalDesc = ''; var pgSave_currentGoalTotal = 0; var noticeOnlyBC = botName + 'Only broadcasters are able to use that command.'; var noticeOnlyBCMod1 = botName + 'Only broadcasters and moderators are able to use that command.'; var noticeOnlyBCMod2 = botName + 'Only broadcasters and "Standard/Advanced" moderator levels are able to use that command.'; var noticeOnlyBCMod3 = botName + 'Only broadcasters and the "Advanced" moderator level are able to use that command.'; var progressiveGoalDescription1 = cb.settings.progressiveGoalDescription1; var progressiveGoalDescription2 = cb.settings.progressiveGoalDescription2; var progressiveGoalDescription3 = cb.settings.progressiveGoalDescription3; var progressiveGoalDescription4 = cb.settings.progressiveGoalDescription4; var progressiveGoalDescription5 = cb.settings.progressiveGoalDescription5; var progressiveGoalDescription6 = cb.settings.progressiveGoalDescription6; var progressiveGoalDescription7 = cb.settings.progressiveGoalDescription7; var progressiveGoalDescription8 = cb.settings.progressiveGoalDescription8; var progressiveGoalDescription9 = cb.settings.progressiveGoalDescription9; var progressiveGoalDescription10 = cb.settings.progressiveGoalDescription10; var progressiveGoalDescription11 = cb.settings.progressiveGoalDescription11; var progressiveGoalDescription12 = cb.settings.progressiveGoalDescription12; var progressiveGoalDescription13 = cb.settings.progressiveGoalDescription13; var progressiveGoalDescription14 = cb.settings.progressiveGoalDescription14; var progressiveGoalDescription15 = cb.settings.progressiveGoalDescription15; var progressiveGoalDescription16 = cb.settings.progressiveGoalDescription16; var progressiveGoalDescription17 = cb.settings.progressiveGoalDescription17; var progressiveGoalDescription18 = cb.settings.progressiveGoalDescription18; var progressiveGoalDescription19 = cb.settings.progressiveGoalDescription19; var progressiveGoalDescription20 = cb.settings.progressiveGoalDescription20; var progressiveGoalAmount1 = cb.settings.progressiveGoalAmount1; var progressiveGoalAmount2 = cb.settings.progressiveGoalAmount2; var progressiveGoalAmount3 = cb.settings.progressiveGoalAmount3; var progressiveGoalAmount4 = cb.settings.progressiveGoalAmount4; var progressiveGoalAmount5 = cb.settings.progressiveGoalAmount5; var progressiveGoalAmount6 = cb.settings.progressiveGoalAmount6; var progressiveGoalAmount7 = cb.settings.progressiveGoalAmount7; var progressiveGoalAmount8 = cb.settings.progressiveGoalAmount8; var progressiveGoalAmount9 = cb.settings.progressiveGoalAmount9; var progressiveGoalAmount10 = cb.settings.progressiveGoalAmount10; var progressiveGoalAmount11 = cb.settings.progressiveGoalAmount11; var progressiveGoalAmount12 = cb.settings.progressiveGoalAmount12; var progressiveGoalAmount13 = cb.settings.progressiveGoalAmount13; var progressiveGoalAmount14 = cb.settings.progressiveGoalAmount14; var progressiveGoalAmount15 = cb.settings.progressiveGoalAmount15; var progressiveGoalAmount16 = cb.settings.progressiveGoalAmount16; var progressiveGoalAmount17 = cb.settings.progressiveGoalAmount17; var progressiveGoalAmount18 = cb.settings.progressiveGoalAmount18; var progressiveGoalAmount19 = cb.settings.progressiveGoalAmount19; var progressiveGoalAmount20 = cb.settings.progressiveGoalAmount20; // Arrays */ var moderatorList = {name: [], type: []}; var modsInShow = []; var tipCountArray = {name: [], amount: []}; var progGoalArray = {desc: [], amt: [], recyc: []}; var drawpanel = {panel: {}}; // *********************************** Initialize ************************************** if (initialize == 0) { cb.sendNotice(' Dorothy\'s Tip Goals v2.1 '); let intromessage = '\u26D4 Version 2.1 was released on April 8, 2021 \u26D4'; intromessage += '\n \u2705 Dorothy\'s Tip Goals was written by CB users chelsea2950 and butter_my_toast.'; intromessage += '\n \u2705 You can read the full list of features, commands, and release notes on the bot description page:'; intromessage += '\n \u2705 https://chaturbate.com/apps/app_details/dorothys-tip-goals/ '; intromessage += '\n \u2705 ' + wordWrap('Version 2.0 was a complete upgrade to now include all of the features from the Progressive Goals portion of Dorothy\'s UltraApp'); intromessage += '\n \u2705 ' + wordWrap('Be sure to check out all of the new options, such as counting up or down, room title formatting, color themes, gradient color patterns, notice border patterns and more.'); intromessage += '\n \u2705 They are a great way to further personalize your room!'; intromessage += '\n \u2705 To display the full command list in the chat type: /goalhelp'; intromessage += '\n \u2705 To display the App info and latest release notes, type: /about'; intromessage += '\n \u2705 To display the moderator trust level details, type: /modlevels'; cb.sendNotice(intromessage, BC, appErrorColor); // *** Personalized names if (cb.settings.bctext) { bcText = cb.settings.bctext; } else { bcText = 'The Broadcaster'; } //*** Initialize panel and notice colors if (cb.settings.panelBackground != 'default - no image') { if (cbjs.arrayContains(backgroundArray.menu,cb.settings.panelBackground)) { var initbackground = backgroundArray.command[backgroundArray.menu.indexOf(cb.settings.panelBackground)]; customizePanelBackground(initbackground,BC); customizePanelText('',BC); } else { botPanel = false; cb.sendNotice('A panel background was chosen but it does not exist, using the default panel background.', BC, appNoticeColor); } } else { botPanel = false; } setBgColor(BC); setThemeTextColor(BC); noticeBorderChar(); for (let loadindex = 1; loadindex <= 20; loadindex++) { var goaldesc = this["progressiveGoalDescription"+loadindex]; var goalamt = this["progressiveGoalAmount"+loadindex]; var goalrecyc = this["progressiveGoalRecycle"+loadindex]; if (goaldesc && goalamt > 0) { progGoalArray.desc.push(goaldesc); progGoalArray.amt.push(goalamt); progGoalArray.recyc.push(goalrecyc); } } var validGoals = false; if (progGoalArray.desc.length <= 0) { cb.sendNotice(botName + 'No goals have been defined. Please restart the Tip Goal App and define the goals you would like to use, or remove dashes/negative signs if they were all previously disabled', BC, appNoticeColor); changeRoomSubject(); cb.drawPanel(); } else { validGoals = true; startGoals(); } initialize = 1; } // ********************** Functions ****************************** //********** Check Next Line Function and Word Wrap ************** function checkNextLine(nlmessage) { var nlmessagearray = nlmessage.split(' '); var nllinearray = []; var templinearray = []; var lineidx = 0; var currlineidx = 0; var nlreplace = false; var nlsubfound = true; while (nlsubfound) { if (cbjs.arrayContains(nlmessagearray,'{n}')) { let nlmsgindex = nlmessagearray.indexOf('{n}'); templinearray = nlmessagearray.slice(currlineidx,nlmsgindex); nllinearray[lineidx] = wordWrap(cbjs.arrayJoin(templinearray,' ')); templinearray = nlmessagearray.slice(nlmsgindex+1); nllinearray[lineidx+1] = wordWrap(cbjs.arrayJoin(templinearray,' ')); lineidx++; currlineidx = nlmsgindex+1; nlreplace = true; } else { nlsubfound = false; } } if (nlreplace) { return cbjs.arrayJoin(nllinearray,'\n'); } else { return wordWrap(nlmessage); } } function wordWrap(wrapstring) { if (wrapMaxLength > 0) { let newlinechar = '\n'; let splitstring = ''; while (wrapstring.length > wrapMaxLength) { let spacefound = false; for (var wwidx = wrapMaxLength - 1; wwidx >= 0; wwidx--) { if (testWhite(wrapstring.charAt(wwidx))) { splitstring = splitstring + [wrapstring.slice(0, wwidx), newlinechar].join(''); wrapstring = wrapstring.slice(wwidx + 1); spacefound = true; break; } } if (!spacefound) { splitstring += [wrapstring.slice(0, wrapMaxLength), newlinechar].join(''); wrapstring = wrapstring.slice(wrapMaxLength); } } return splitstring + wrapstring; } else { return wrapstring; } } function testWhite(whitestring) { var white = new RegExp(/^\s$/); return white.test(whitestring.charAt(0)); } //********** Check Username Function ************** function checkUsername(ckusermessage,chkuser) { var responsemessagearray = ckusermessage.split(' '); var userreplace = false; if (cbjs.arrayContains(responsemessagearray,'{username}')) { let msgindex = responsemessagearray.indexOf('{username}'); responsemessagearray[msgindex] = chkuser; userreplace = true; } else if (cbjs.arrayContains(responsemessagearray,'{username},')) { let msgindex = responsemessagearray.indexOf('{username},'); responsemessagearray[msgindex] = chkuser + ','; userreplace = true; } else if (cbjs.arrayContains(responsemessagearray,'{username}!')) { let msgindex = responsemessagearray.indexOf('{username}!'); responsemessagearray[msgindex] = chkuser + '!'; userreplace = true; } else if (cbjs.arrayContains(responsemessagearray,'{username}:')) { let msgindex = responsemessagearray.indexOf('{username}:'); responsemessagearray[msgindex] = chkuser + ':'; userreplace = true; } else if (cbjs.arrayContains(responsemessagearray,'{username}.')) { let msgindex = responsemessagearray.indexOf('{username}.'); responsemessagearray[msgindex] = chkuser + '.'; userreplace = true; } if (userreplace) { return cbjs.arrayJoin(responsemessagearray,' '); } else { return ckusermessage; } } //********** Build Notice Borders ************** function noticeBorderChar() { if (cb.settings.noticeSepStyle == 'Custom Emoji Below') { borderCharSpacing = 'emoji'; if (borderChar) { if (borderChar.includes(':') || borderChar.includes('\\')) { cb.sendNotice(botName + ' You have configured configured the notice border style as "Custom Emoji" but the value contains ":" or "\\" (CB gifs are not allowed). Defaulting to an emoji of Heavy Dashed Line " \u2796 ".', BC, appNoticeColor); borderChar = '\u2796'; } } else { borderChar = '\u2796'; cb.sendNotice(botName + ' You have configured configured the notice border style as "Custom Emoji" but an emoji is not defined. Defaulting to an emoji of Heavy Dashed Line " \u2796 ".', BC, appNoticeColor); } } else if (cb.settings.noticeSepStyle == 'Custom Unicode Character Below') { borderCharSpacing = 'unicode'; if (borderChar) { if (borderChar.includes(':')) { cb.sendNotice(botName + ' You have configured configured the notice border style as "Custom Unicode Character" but the value contains ":" (CB gifs are not allowed). Defaulting to a character of Heavy Dashed Line " \u268A ".', BC, appNoticeColor); borderChar = '\u268A'; } } else { borderChar = '\u268A'; cb.sendNotice(botName + ' You have configured configured the notice border style as "Custom Unicode Character" but a character is not defined. Defaulting to a character of Heavy Dashed Line " \u268A ".', BC, appNoticeColor); } } else if (cb.settings.noticeSepStyle == 'Heavy Dashed Line') { borderCharSpacing = 'unicode'; borderChar = '\u268A'; } else if (cb.settings.noticeSepStyle == 'Light Dashed Line') { borderCharSpacing = 'light'; borderChar = '-'; } else { borderCharSpacing = 'none'; } switch (borderCharSpacing) { case 'emoji': borderWelcomeTop = noticeBorder('top','WELCOME',11,false,true) + '\n'; borderWelcomeBottom = '\n' + noticeBorder('bottom','',13,false,true); borderNoticeTop = noticeBorder('top','TIP GOALS',11,false,true) + '\n'; borderNoticeBottom = '\n' + noticeBorder('bottom','',13,false,true); borderGoalCompleteTop = noticeBorder('top','',13,false,true) + '\n'; borderGoalCompleteBottom = '\n' + noticeBorder('bottom','',13,false,true); break; case 'unicode': borderWelcomeTop = noticeBorder('top','WELCOME',20,false,false); borderWelcomeBottom = noticeBorder('bottom','',22,true,false); borderNoticeTop = noticeBorder('top','TIP GOALS',20,false,false); borderNoticeBottom = noticeBorder('bottom','',22,true,false); borderGoalCompleteTop = noticeBorder('top','',22,false,false); borderGoalCompleteBottom = noticeBorder('bottom','',22,false,false); break; case 'light': borderWelcomeTop = noticeBorder('top','WELCOME',42,true,false); borderWelcomeBottom = noticeBorder('bottom','',48,false,false); borderNoticeTop = noticeBorder('top','TIP GOALS',42,false,false); borderNoticeBottom = noticeBorder('bottom','',48,false,false); borderGoalCompleteTop = noticeBorder('top','',48,true,false); borderGoalCompleteBottom = noticeBorder('bottom','',48,true,false); break; case 'none': borderWelcomeTop = 'WELCOME:'; borderNoticeTop = 'TIP GOALS:'; borderGoalCompleteTop = noticeBorder('top','',48,true,false); borderGoalCompleteBottom = noticeBorder('bottom','',48,true,false); break; } } function noticeBorder(bordertopbtm,bordertext,bordernumchar,bordernumaddone,borderdispspace) { let outcharstring = ''; let halfcharstring = ''; let midchar = '\u25CF'; let dispnumber = 0; if (borderCharSpacing == 'none') { if (bordertopbtm == 'top') { outcharstring = bordertext; } } else { for (let charidx = 1; charidx <= bordernumchar; charidx++) { if (borderdispspace) { halfcharstring += borderChar + ' '; } else { halfcharstring += borderChar; } } if (bordertopbtm == 'top') { outcharstring += halfcharstring + ' ' + bordertext + ' ' + halfcharstring; if (bordernumaddone) { outcharstring += borderChar; } } else if (bordertopbtm == 'bottom') { if (borderdispspace) { outcharstring += halfcharstring + halfcharstring; } else { outcharstring += halfcharstring + ' ' + midchar + ' ' + halfcharstring; } if (bordernumaddone) { outcharstring += borderChar; } } } return outcharstring; } // Generic functions to set the colors function setThemeTextColor(settextsendto) { progGoalTextColor = '#000000'; if (colorTheme == 'Custom') { var temptextcolor = cb.settings.colorThemeCustText; if (/^#[0-9A-F]{6}$/i.test(temptextcolor)) { progGoalTextColor = temptextcolor; } else if (/^[0-9A-F]{6}$/i.test(temptextcolor)) { progGoalTextColor = '#' + temptextcolor; } } else if (colorTheme != 'None') { if (cbjs.arrayContains(themeArray.name,colorTheme)) { let themeidx = themeArray.name.indexOf(colorTheme); progGoalTextColor = themeArray.textcolor[themeidx]; } else { cb.sendNotice(botName + 'Invalid theme setting of "' + colorTheme + '" when setting text color. \nDefaulting to no theme used and black text.', settextsendto, appNoticeColor); colorTheme = 'None'; } } } function setPanelTextColor(sptcolor,sptcsendto) { if (cbjs.arrayContains(textColorArray.dispname,sptcolor)) { var txtclridx = textColorArray.dispname.indexOf(sptcolor); return textColorArray.colorID[txtclridx]; } else { if (/^#[0-9A-F]{6}$/i.test(sptcolor)) { return sptcolor; } else if (/^[0-9A-F]{6}$/i.test(sptcolor)) { return '#' + sptcolor; } else { return 'default'; } } } function setBgColor(setbgsendto) { progGoalBgColor = '#FFFFFF'; var graddir = ''; if (cb.settings.colorsGradientDirection == 'Linear, left to right') { graddir = 'to right'; } else if (cb.settings.colorsGradientDirection == 'Linear, top to bottom') { graddir = 'to bottom'; } else if (cb.settings.colorsGradientDirection == 'Linear, diagonally') { graddir = 'to right bottom'; } else if (cb.settings.colorsGradientDirection == 'None - Solid Color') { graddir = 'none'; } if (colorTheme == 'Custom') { var themecustbg1 = ''; var themecustbg2 = ''; var themecustbg3 = ''; if (cb.settings.colorThemeCustBg1) { if (/^#[0-9A-F]{6}$/i.test(cb.settings.colorThemeCustBg1)) { themecustbg1 = cb.settings.colorThemeCustBg1; } else if (/^[0-9A-F]{6}$/i.test(cb.settings.colorThemeCustBg1)) { themecustbg1 = '#' + cb.settings.colorThemeCustBg1; } else { if (!themeWarning2) { cb.sendNotice(botName + 'Warning! Custom color theme selected but Background 1 is not in the correct hex color code format. \nDefaulting to no theme used.', setbgsendto, appNoticeColor); themeWarning2 = true; } colorTheme = 'None'; } } else { if (!themeWarning3) { cb.sendNotice(botName + 'Warning! Custom color theme selected but Background 1 is not configured. \nDefaulting to no theme used.', setbgsendto, appNoticeColor); themeWarning3 = true; } colorTheme = 'None'; } if (cb.settings.colorThemeCustBg2) { if (/^#[0-9A-F]{6}$/i.test(cb.settings.colorThemeCustBg2)) { themecustbg2 = cb.settings.colorThemeCustBg2; } else if (/^[0-9A-F]{6}$/i.test(cb.settings.colorThemeCustBg2)) { themecustbg2 = '#' + cb.settings.colorThemeCustBg2; } else { themecustbg2 = '#FFFFFF'; if (!themeWarning4) { cb.sendNotice(botName + 'Warning! Custom color theme selected but Background 2 is not configured with a proper hex color code. \nDefaulting second color to white.', setbgsendto, appNoticeColor); themeWarning4 = true; } } } else if (graddir != 'none') { themecustbg2 = '#FFFFFF'; if (!themeWarning5) { cb.sendNotice(botName + 'Warning! Custom color theme selected but Background 2 is not configured. \nAt least two colors are required, defaulting second color to white.', setbgsendto, appNoticeColor); themeWarning5 = true; } } var numbercustcolors = 2; if (cb.settings.colorThemeCustBg3) { numbercustcolors = 3; if (/^#[0-9A-F]{6}$/i.test(cb.settings.colorThemeCustBg3)) { themecustbg3 = cb.settings.colorThemeCustBg3; } else if (/^[0-9A-F]{6}$/i.test(cb.settings.colorThemeCustBg3)) { themecustbg3 = '#' + cb.settings.colorThemeCustBg3; } else { themecustbg3 = '#FFFFFF'; } } if (colorTheme != 'None') { if (graddir == 'none') { progGoalBgColor = themecustbg1; } else { if (numbercustcolors == 2) { progGoalBgColor = 'linear-gradient(' + graddir + ', ' + themecustbg1 + ', ' + themecustbg2 + ')'; } else { progGoalBgColor = 'linear-gradient(' + graddir + ', ' + themecustbg1 + ', ' + themecustbg2 + ', ' + themecustbg3 + ')'; } } } } else if (colorTheme != 'None') { if (cbjs.arrayContains(themeArray.name,colorTheme)) { var themeidx = themeArray.name.indexOf(colorTheme); progGoalBgColor = themeArray.colorID[themeidx]; } else { cb.sendNotice(botName + 'Warning! Invalid theme setting of "' + colorTheme + '". \nDefaulting to no theme used.', setbgsendto, appNoticeColor); colorTheme = 'None'; } } } function leftJustify(textstring,line) { var textstringlength = textstring.length; if (fontSize == 11) { if (line == 1) { if (textstringlength < 4) { return 114; } else if (textstringlength < 6) { return 109; } else if (textstringlength < 8) { return 104; } else if (textstringlength < 10) { return 100; } else if (textstringlength < 12) { return 95; } else if (textstringlength < 14) { return 90; } else if (textstringlength < 16) { return 86; } else if (textstringlength < 18) { return 82; } else if (textstringlength < 20) { return 77; } else if (textstringlength < 22) { return 72; } else if (textstringlength < 24) { return 67; } else if (textstringlength < 26) { return 62; } else if (textstringlength < 28) { return 58; } else if (textstringlength < 30) { return 53; } else if (textstringlength < 32) { return 49; } else if (textstringlength < 34) { return 44; } else if (textstringlength < 37) { return 39; } else if (textstringlength < 40) { return 34; } else if (textstringlength < 42) { return 30; } else if (textstringlength < 44) { return 26; } else if (textstringlength < 47) { return 21; } else if (textstringlength < 49) { return 16; } else if (textstringlength < 51) { return 11; } else { return 7; } } else { if (textstringlength < 4) { return 114; } else if (textstringlength < 6) { return 110; } else if (textstringlength < 8) { return 105; } else if (textstringlength < 10) { return 100; } else if (textstringlength < 12) { return 97; } else if (textstringlength < 14) { return 93; } else if (textstringlength < 16) { return 88; } else if (textstringlength < 18) { return 83; } else if (textstringlength < 20) { return 79; } else if (textstringlength < 22) { return 74; } else if (textstringlength < 24) { return 71; } else if (textstringlength < 26) { return 66; } else if (textstringlength < 28) { return 61; } else if (textstringlength < 30) { return 57; } else if (textstringlength < 32) { return 53; } else if (textstringlength < 34) { return 48; } else if (textstringlength < 37) { return 44; } else if (textstringlength < 39) { return 39; } else if (textstringlength < 42) { return 34; } else if (textstringlength < 44) { return 29; } else if (textstringlength < 47) { return 24; } else if (textstringlength < 49) { return 19; } else if (textstringlength < 52) { return 14; } else { return 7; } } } else { if (line == 1) { if (textstringlength < 4) { return 113; } else if (textstringlength < 6) { return 108; } else if (textstringlength < 8) { return 103; } else if (textstringlength < 10) { return 99; } else if (textstringlength < 12) { return 94; } else if (textstringlength < 14) { return 89; } else if (textstringlength < 16) { return 84; } else if (textstringlength < 18) { return 80; } else if (textstringlength < 20) { return 75; } else if (textstringlength < 22) { return 70; } else if (textstringlength < 24) { return 65; } else if (textstringlength < 26) { return 60; } else if (textstringlength < 28) { return 55; } else if (textstringlength < 30) { return 50; } else if (textstringlength < 32) { return 46; } else if (textstringlength < 34) { return 41; } else if (textstringlength < 37) { return 36; } else if (textstringlength < 40) { return 31; } else if (textstringlength < 42) { return 26; } else if (textstringlength < 44) { return 22; } else if (textstringlength < 47) { return 17; } else if (textstringlength < 49) { return 12; } else if (textstringlength < 51) { return 7; } else { return 3; } } else { if (textstringlength < 4) { return 113; } else if (textstringlength < 6) { return 109; } else if (textstringlength < 8) { return 104; } else if (textstringlength < 10) { return 99; } else if (textstringlength < 12) { return 95; } else if (textstringlength < 14) { return 91; } else if (textstringlength < 16) { return 86; } else if (textstringlength < 18) { return 81; } else if (textstringlength < 20) { return 77; } else if (textstringlength < 22) { return 72; } else if (textstringlength < 24) { return 68; } else if (textstringlength < 26) { return 63; } else if (textstringlength < 28) { return 58; } else if (textstringlength < 30) { return 54; } else if (textstringlength < 32) { return 50; } else if (textstringlength < 34) { return 45; } else if (textstringlength < 37) { return 40; } else if (textstringlength < 39) { return 35; } else if (textstringlength < 42) { return 30; } else if (textstringlength < 44) { return 25; } else if (textstringlength < 47) { return 20; } else if (textstringlength < 49) { return 15; } else if (textstringlength < 52) { return 10; } else { return 3; } } } } //********** Tipper List ************** function findTipper(ftuser) { for (var i = 0; i < tipCountArray.name.length; i++) { if(tipCountArray.name[i] == ftuser) { break; } } return i; } //********** Reset current feature ************** function resetApp() { initProgGoal(); cb.drawPanel(); } //********** Set custom panel text and background ************** function customizePanelText(cptcolor,cptsendto) { if (!cptcolor && cb.settings.panelTextColor == 'Custom') { var textcolorchk = setPanelTextColor(cb.settings.panelCustomTextColor,cptsendto); if (textcolorchk == 'default') { cb.sendNotice('Draw Panel Text Color - Error while setting the text color. It has to be in a HEX format.', cptsendto, appNoticeColor, ''); } else { textColor = textcolorchk; cb.drawPanel(); } } else if (cptcolor) { textcolorchk = setPanelTextColor(cptcolor,cptsendto); if (textcolorchk == 'default') { cb.sendNotice('Draw Panel Text Color - Error while setting the text color. It has to be in a HEX format.', cptsendto, appNoticeColor, ''); } else { textColor = textcolorchk; cb.drawPanel(); } } else { textColor = setPanelTextColor(cb.settings.panelTextColor,cptsendto); cb.drawPanel(); } } function customizePanelBackground(newbackground,sendto) { botPanel = false; if (cbjs.arrayContains(backgroundArray.command,newbackground)) { var bgindex = backgroundArray.command.indexOf(newbackground); // dorothy is the testbed user if (BC == 'dorothy') { if (backgroundArray.command[bgindex] == 'custom') { if (cbjs.arrayContains(backgroundArrayCustom.command,BC)) { var custindex1 = backgroundArrayCustom.command.indexOf(BC); backgroundImage = backgroundArrayCustom.devfile[custindex1]; botPanel = true; currentPanel = newbackground; cb.drawPanel(); } else { cb.sendNotice('You have requested a personalized background, but you are not the room owner for a custom background, please choose again.', sendto, appNoticeColor, ''); } } else { backgroundImage = backgroundArray.devfile[bgindex]; botPanel = true; currentPanel = newbackground; cb.drawPanel(); } } else { if (backgroundArray.command[bgindex] == 'custom') { if (cbjs.arrayContains(backgroundArrayCustom.command,BC)) { var custindex2 = backgroundArrayCustom.command.indexOf(BC); if (appVersion == 'Show1') { backgroundImage = backgroundArrayCustom.livefile[custindex2]; } else if (appVersion == 'Show2') { backgroundImage = backgroundArrayCustom.livefile2[custindex2]; } botPanel = true; currentPanel = newbackground; cb.drawPanel(); } else { cb.sendNotice('You have requested a personalized background, but you are not the room owner for a custom background, please choose again.', sendto, appNoticeColor, ''); } } else { if (appVersion == 'Show1') { backgroundImage = backgroundArray.livefile[bgindex]; } else if (appVersion == 'Show2') { backgroundImage = backgroundArray.livefile2[bgindex]; } botPanel = true; currentPanel = newbackground; cb.drawPanel(); } } } else { cb.sendNotice('Invalid background name. The valid names are: \n' + cbjs.arrayJoin(backgroundArray.command, ', '), sendto, appNoticeColor, ''); } } function customizeColorTheme(newcolortheme,newthemesendto) { if (cbjs.arrayContains(themeArray.shortcut,newcolortheme)) { var themeindex = themeArray.shortcut.indexOf(newcolortheme); if (newcolortheme == 'custom') { if (cb.settings.colorThemeCustBg1) { if (cb.settings.colorThemeCustText) { colorTheme = 'Custom'; setBgColor(newthemesendto); setThemeTextColor(newthemesendto); cb.sendNotice('You have updated the color theme to "Custom".', newthemesendto, appNoticeColor, ''); } else { cb.sendNotice('You have requested a custom color theme, but a custom text color is not defined in setting "3M5".', newthemesendto, appNoticeColor, ''); } } else { cb.sendNotice('You have requested a custom color theme, but at least one custom color is not defined in setting "3M1".', newthemesendto, appNoticeColor, ''); } } else { colorTheme = themeArray.name[themeindex]; setBgColor(newthemesendto); setThemeTextColor(newthemesendto); cb.sendNotice('You have updated the color theme to "' + colorTheme + '".', newthemesendto, appNoticeColor, ''); } } else { cb.sendNotice('Invalid color theme name. The valid names are: \n' + cbjs.arrayJoin(themeArray.shortcut, ', '), newthemesendto, appNoticeColor, ''); } } //******************** Goal Bar ************************** function goalBar(currentamt,totalamt) { var percentbar = 0; if (currentamt > 0 && totalamt > 0) { percentbar = Math.round(100*(currentamt/totalamt)); } } function charRepeat(repeatchar,repeatln) { var repeatstring = ''; for (var charindex = 1; charindex <= repeatln; charindex++) { repeatstring += repeatchar } return repeatstring; } // *********************************** Progressive Goal Functions ************************************** function recordTip(tippedamount,tippedby) { if (validGoals) { if (tippedby != 'bc') { currentAppTotalGoal += tippedamount; currentSessionTotal += tippedamount; } if (!finalGoalMet) { if (cb.settings.progressiveUpDown == 'Count Up To Goal') { savedCurrentGoalTips = currentGoalTips; currentGoalTips += tippedamount; if (currentGoalTips >= currentGoalTotal) { if (progressiveAutoNext == 'Auto-start next') { exceedGoal(tippedamount); } else { if (!currentGoalMet) { goalComplete(); } } } } else { savedCurrentGoalTips = currentGoalTips; currentGoalTips -= tippedamount; if (currentGoalTips <= 0) { if (progressiveAutoNext == 'Auto-start next') { exceedGoal(tippedamount); } else { if (!currentGoalMet) { goalComplete(); } } } } if (cb.settings.roomTitleRemTokens != 'No') { changeRoomSubject(); } } cb.drawPanel(); } else { if (tippedby != 'bc') { currentSessionTotal += tippedamount; } cb.drawPanel(); } } function exceedGoal(tippedamountexc) { var excesstip = 0; if (cb.settings.progressiveUpDown == 'Count Up To Goal') { excesstip = tippedamountexc - (currentGoalTotal - savedCurrentGoalTips); goalComplete(); if (!finalGoalMet) { nextGoal(); currentGoalTips = excesstip; if (currentGoalTips >= currentGoalTotal) { savedCurrentGoalTips = 0; exceedGoal(currentGoalTips); } } } else { excesstip = tippedamountexc - savedCurrentGoalTips; goalComplete(); if (!finalGoalMet) { nextGoal(); currentGoalTips = currentGoalTotal - excesstip; if (currentGoalTips <= 0) { savedCurrentGoalTips = 0; exceedGoal(0 - currentGoalTips); } } } } function goalComplete() { currentGoalMet = true; if (progGoalArray.desc.length == 1) { cb.sendNotice(borderGoalCompleteTop + '\n :CGGoal15 The goal (' + progGoalArray.desc[currentGoal-1] + ') has been met!! :CGGoal15 \n' + borderGoalCompleteBottom, '', progGoalBgColor, progGoalTextColor, 'bold'); finalGoalMet = true; changeRoomSubject(); } else if (currentGoal < progGoalArray.desc.length || progressiveAutoNext == 'Select next goal from list') { cb.sendNotice(borderGoalCompleteTop + '\n :CGGoal15 Goal #' + currentGoal + ' (' + progGoalArray.desc[currentGoal-1] + ') has been met!! :CGGoal15 \n' + borderGoalCompleteBottom, '', progGoalBgColor, progGoalTextColor, 'bold'); if (progressiveAutoNext == 'Manually start next') { if (modLevel == 'Standard' || modLevel == 'Advanced') { cb.sendNotice('Note to mods: The goal has been completed and per configuration the app is awaiting manual advance to the next goal using the "/next" command', '', appNoticeColor, '', '', 'red'); } cb.sendNotice('The goal has been completed and per configuration the app is awaiting manual advance using the "/next" command', BC, appNoticeColor, '', ''); } else if (progressiveAutoNext == 'Select next goal from list') { if (modLevel == 'Standard' || modLevel == 'Advanced') { cb.sendNotice('Note to mods: The current goal (#' + currentGoal + ') has been completed.\nYou can now choose the next goal from the below list by using the command /goal X, where X is the goal number. \nYou can select a new goal or re-use one that was already used. \nOr you can use the /next command to do the next goal in order, goal #' + (currentGoal+1) + '.' + listGoalsForSelect(), '', appNoticeColor, '', '', 'red'); } cb.sendNotice('The current goal (#' + currentGoal + ') has been completed.\nYou can now choose your next goal from the below list by using the command /goal X, where X is the goal number. \nYou can select a new goal or re-use one you\'ve already used. \nOr you can use the /next command to do the next goal in order, goal #' + (currentGoal+1) + '.' + listGoalsForSelect(), BC, appNoticeColor, '', ''); } } else if (currentGoal == progGoalArray.desc.length) { cb.sendNotice(borderGoalCompleteTop + '\n :CGGoal15 Final Goal (' + progGoalArray.desc[currentGoal-1] + ') has been met!! :CGGoal15 \n \uD83C\uDFC6 \uD83C\uDFC6 \uD83C\uDFC6 ' + getTopTipper() + ' was the top tipper!!! \uD83C\uDFC6 \uD83C\uDFC6 \uD83C\uDFC6 \n' + borderGoalCompleteBottom, '', progGoalBgColor, progGoalTextColor, 'bold'); finalGoalMet = true; changeRoomSubject(); } } function skipGoal() { goalComplete(); if (!finalGoalMet) { nextGoal(); } cb.drawPanel(); } function getTopTipper() { var swapped, temp1, temp2; do {swapped = false; for (var i = 0; i < tipCountArray.amount.length ; i++) { if (tipCountArray.amount[i] < tipCountArray.amount[i + 1]) { temp1 = tipCountArray.amount[i]; temp2 = tipCountArray.name[i]; tipCountArray.amount[i] = tipCountArray.amount[i + 1]; tipCountArray.amount[i + 1] = temp1; tipCountArray.name[i] = tipCountArray.name[i + 1]; tipCountArray.name[i + 1] = temp2; swapped = true; } } } while (swapped); return tipCountArray.name[0]; } function nextGoal() { currentGoal++; currentGoalDesc = progGoalArray.desc[currentGoal-1]; currentGoalTotal = progGoalArray.amt[currentGoal-1]; if (cb.settings.progressiveUpDown == 'Count Up To Goal') { currentGoalTips = 0; } else { currentGoalTips = currentGoalTotal; } currentGoalMet = false; changeRoomSubject(); } function buildSubject(currenttext,addition) { if (currenttext != '') { return currenttext + ' -- ' + addition; } else { return addition; } } function changeRoomSubject() { var addsubject = ''; var newsubject = ''; var newtokens = 0; if (validGoals) { if (cb.settings.roomTitleRemTokens == 'Yes, at beginning') { if (cb.settings.progressiveUpDown == 'Count Down To Zero') { newtokens = (currentGoalTips > 0 ? currentGoalTips : 0); } else { newtokens = (currentGoalTotal-(currentGoalTips > currentGoalTotal ? currentGoalTotal : currentGoalTips)); } newsubject += ' [' + newtokens + ' token' + (newtokens == 1 ? '' : 's') + ' to goal]'; } if (roomTitleTextPosn == 'Before' && goalSubjectText) { addsubject = goalSubjectText; newsubject = buildSubject(newsubject,addsubject); } if (roomTitleFormat == 'All' || roomTitleFormat == 'Room Title and Current Goal') { if (!finalGoalMet) { if (cb.settings.progressiveUpDown == 'Count Up To Goal') { addsubject = 'Current Goal: ' + currentGoalDesc + ' at ' + currentGoalTotal + ' tokens'; newsubject = buildSubject(newsubject,addsubject); } else { addsubject = 'Current Goal: ' + currentGoalDesc + ' once countdown reaches zero'; newsubject = buildSubject(newsubject,addsubject); } if (roomTitleFormat == 'All') { if (progGoalArray.desc.length >= (currentGoal + 1)) { newsubject += ' -- Next Goal: ' + progGoalArray.desc[currentGoal]; } else if (progGoalArray.desc.length > 1) { newsubject += ' -- This is the Last Goal! '; } } } else { addsubject = 'All Goals Have Been Completed!!! '; newsubject = buildSubject(newsubject,addsubject); } } if (roomTitleTextPosn == 'After' && goalSubjectText) { newsubject = buildSubject(newsubject,goalSubjectText); } if (cb.settings.roomTitleRemTokens == 'Yes, at end') { if (cb.settings.progressiveUpDown == 'Count Up To Goal') { newtokens = (currentGoalTotal-(currentGoalTips > currentGoalTotal ? currentGoalTotal : currentGoalTips)); } else { newtokens = (currentGoalTips > 0 ? currentGoalTips : 0); } newsubject += ' [' + newtokens + ' token' + (newtokens == 1 ? '' : 's') + ' to goal]'; } cb.changeRoomSubject(newsubject); } else { newsubject = 'Welcome to ' + bcText + '\'s room'; cb.changeRoomSubject(newsubject); } } function listGoalsForSelect() { var listoutstring = ''; var listselindex = 0; while (progGoalArray.amt[listselindex] > 0 && progGoalArray.desc[listselindex] != null && progGoalArray.desc[listselindex] != '') { listoutstring += '\nGoal #' + (listselindex+1) + ' : ' + progGoalArray.desc[listselindex] + ' (' + progGoalArray.amt[listselindex] + ' tokens)'; listselindex++; } if (listselindex > 0) { return listoutstring; } else { return 'There are no goals configured'; } } function goalNotices(lggroup,lgreqby,listmode,lgcallmode) { var lgoutstring = borderNoticeTop; var listgoalssendto = ''; var listindex = 0; if (lggroup == 'all') { lgoutstring += '\nSent to All:'; } else if (lggroup != 'timer') { lgoutstring += '\nSent to YOU:'; listgoalssendto = lgreqby; } if (finalGoalMet) { lgoutstring += '\nAll Goals have been completed!'; } else { lgoutstring += '\nYou can tip to help reach the current goal.'; if (cb.settings.progressiveUpDown == 'Count Up To Goal') { lgoutstring += '\n' + wordWrap('Current Goal: ' + currentGoalDesc + ' at ' + currentGoalTotal + ' tokens (' + (currentGoalTotal-(currentGoalTips > currentGoalTotal ? currentGoalTotal : currentGoalTips)) + ' left)'); } else { lgoutstring += '\n' + wordWrap('Current Goal: ' + currentGoalDesc + ' once countdown reaches zero (' + currentGoalTips + ' remaining)'); } if (progGoalArray.desc.length <= 1) { lgoutstring += '\nThere is a single goal for the show.'; } else { lgoutstring += '\nThere are ' + totalProgGoals + ' total goals for the show.'; if (progressiveAutoNext == 'Select next goal from list') { lgoutstring += '\nThe broadcaster is choosing the next goal after each goal finishes.'; lgoutstring += '\nTherefore the goals may not be completed in order.'; listmode = 'a'; } } } if (((cb.settings.progressiveIncludeGoals == 'Yes' && !finalGoalMet) || lgcallmode == 'cmd') && progGoalArray.desc.length > 0 && currentGoal > 0) { if (listmode == 'r') { listindex = (currentGoal-1); } lgoutstring += '\n' + (listmode == 'a' ? 'Full Goal List: ' : 'Remaining Goal List: '); while (progGoalArray.amt[listindex] > 0 && progGoalArray.desc[listindex] != null && progGoalArray.desc[listindex] != '') { lgoutstring += '\n \u2022 ' + wordWrap('Goal #' + (listindex+1) + ' : ' + progGoalArray.desc[listindex] + ' (' + progGoalArray.amt[listindex] + ' tokens)'); listindex++; } } if (cb.settings.noticeSepStyle != 'No Border') { lgoutstring += '\n' + borderNoticeBottom; } cb.sendNotice(lgoutstring, listgoalssendto, progGoalBgColor, progGoalTextColor, 'bold'); } function startGoals() { initProgGoal(); changeRoomSubject(); initProgGoalsNoticeTimer(); } function initProgGoal() { finalGoalMet = false; currentGoalMet = false; currentGoalTips = 0; currentGoal = 1; totalProgGoals = progGoalArray.desc.length; currentGoalDesc = progGoalArray.desc[currentGoal-1]; currentGoalTotal = progGoalArray.amt[currentGoal-1]; if (cb.settings.progressiveUpDown == 'Count Down To Zero') { currentGoalTips = currentGoalTotal; } if (roomTitleFormat == 'All' && progressiveAutoNext == 'Select next goal from list') { roomTitleFormat = 'Room Title and Current Goal'; } } function initProgGoalsNoticeTimer() { if (!cb.settings.progressiveGoalNoticeInterval) { cb.sendNotice(botName + 'Goal Notice Interval is not set. Using default value of 4.1 minutes.', BC, appNoticeColor); progGoalNoticeInt = 4.1; } else { progGoalNoticeInt = parseFloat(cb.settings.progressiveGoalNoticeInterval); } if (progressiveAutoNext == 'Select next goal from list' && progGoalNoticeInt > 0) { cb.sendNotice(botName + 'Goal advance mode is set to "Select next goal from list", the recurring notice for remaining goals is being disabled.', BC, appNoticeColor); progGoalNoticeInt = 0; } if (progGoalNoticeInt > 0) { if (progGoalNoticeInt < 1) { cb.sendNotice(botName + 'Goal Notice Interval is too short, must be zero to disable, or at least 1 minute. Using default value of 4.1 minutes.', BC, appNoticeColor); progGoalNoticeInt = 4.1; } progGoalNoticeInt *= 60000; progGoalNoticeInt = parseInt(progGoalNoticeInt); cb.setTimeout(progGoalsNotice, progGoalNoticeInt); } } function progGoalsNotice() { if (validGoals && !finalGoalMet) { goalNotices('timer','','r','timer'); cb.setTimeout(progGoalsNotice, progGoalNoticeInt); } } function restartGoal() { currentGoal--; finalGoalMet = false; currentGoalMet = false; nextGoal(); cb.drawPanel(); } // ******************************* Upon user entry of a Message ************************************** cb.onMessage(function (msg) { var rawmsg = msg.m; var msgarray = rawmsg.split(' '); var msguser = msg.user; var msgisbc = (msguser === BC); var command = msgarray[0]; var commandvar1 = parseInt(msgarray[1]); var commandvar2 = parseInt(msgarray[2]); var listregexp = /[,\s]+/; var msgismod = msg.is_mod; var ismodlvlmsg1 = false; var ismodlvlmsg2 = false; var ismodlvlmsg3 = false; if (msgismod) { ismodlvlmsg1 = true; if (modLevel == 'Standard') { ismodlvlmsg2 = true; } else if (modLevel == 'Advanced') { ismodlvlmsg2 = true; ismodlvlmsg3 = true; } } if (msgarray[0].charAt(0) == '/') { var recognizedcmd = false; msg['X-Spam'] = true; var ntc = null; for (var n1 = 1; n1 < msgarray.length; n1++) { if (n1 == 1) ntc = msgarray[n1]; else ntc += ' ' + msgarray[n1]; } var ntc2 = null; for (var n2 = 2; n2 < msgarray.length; n2++) { if (n2 == 2) ntc2 = msgarray[n2]; else ntc2 += ' ' + msgarray[n2]; } var cmdval = null; for (var n3 = 1; n3 < msgarray.length; n3++) { if (n3 == 1) cmdval = msgarray[n3]; else cmdval += ' ' + msgarray[n3]; } switch (command) { //********* General Commands case '/chgpanelbg': { if (msgisbc || ismodlvlmsg2) { if (msgarray[1]) { let newbg = msgarray[1].toLowerCase(); customizePanelBackground(newbg,msguser); } else { cb.sendNotice(botName + 'The /chgpanelbg command requires the entry of a parameter following the command, such as "/chgpanelbg lavalamp". The valid formats are: \n' + cbjs.arrayJoin(backgroundArray.command, ', '), msguser, appNoticeColor); } } else { cb.sendNotice(noticeOnlyBCMod2, msguser, appNoticeColor); } break; } case '/paneltextcolor': { if (msgisbc || ismodlvlmsg2) { var pnltxtclr = rawmsg.substring(16).trim(); if (pnltxtclr) { customizePanelText(pnltxtclr,msguser); } else { cb.sendNotice(botName + 'The /paneltextcolor command requires the entry of a parameter following the command, which represents either the color name or the color hex code, such as "/paneltextcolor Blue" or "/paneltextcolor #0000ff".' , msguser, appNoticeColor); } } else { cb.sendNotice(noticeOnlyBCMod2, msguser, appNoticeColor); } break; } case '/chgtheme': { if (msgisbc || ismodlvlmsg2) { if (msgarray[1]) { let newtheme = msgarray[1].toLowerCase(); customizeColorTheme(newtheme,msguser); } else { cb.sendNotice(botName + 'The /chgtheme command requires the entry of a parameter following the command, such as "/chgtheme pastelrainbow". The valid formats are: \n' + cbjs.arrayJoin(themeArray.shortcut, ', '), msguser, appNoticeColor); } } else { cb.sendNotice(noticeOnlyBCMod2, msguser, appNoticeColor); } break; } case '/next': { if (validGoals) { if (msgisbc || ismodlvlmsg2) { if (finalGoalMet) { cb.sendNotice(botName + 'Command cannot be used once all goals have been completed.', msguser, appNoticeColor); } else if (cb.settings.progressiveUpDown == 'Count Up To Goal' && currentGoalTips < currentGoalTotal) { cb.sendNotice(botName + 'Command cannot be used during goal, it should be used only to manually advance a goal once complete if the auto-advance is off. The /skip command can be used to bypass the rest of a goal.', msguser, appNoticeColor); } else if (cb.settings.progressiveUpDown == 'Count Down To Zero' && currentGoalTips > 0) { cb.sendNotice(botName + 'Command cannot be used during goal, it should be used only to manually advance a goal once complete if the auto-advance is off. The /skip command can be used to bypass the rest of a goal.', msguser, appNoticeColor); } else if (cb.settings.progressiveAutoNext == 'Select next goal from list' && (currentGoal+1) > progGoalArray.desc.length) { cb.sendNotice(botName + 'Already at the highest goal in the list, please select a specific goal with the /goal command, or add another goal.', msguser, appNoticeColor); } else { cb.sendNotice(botName + 'You have manually advanced to the next goal.', msguser, appNoticeColor); nextGoal(); cb.drawPanel(); } } else { cb.sendNotice(noticeOnlyBCMod2, msguser, appNoticeColor); } } else { cb.sendNotice(botName + 'The "/next" command can only be used if the goals have been successfully started.', msguser, appNoticeColor); } break; } case '/skip': { if (validGoals) { if (msgisbc || ismodlvlmsg2) { if (finalGoalMet) { cb.sendNotice(botName + 'Command cannot be used once all goals have been completed.', msguser, appNoticeColor); } else { skipGoal(); cb.sendNotice(botName + 'You have skipped the remainder of the current goal and advanced to the next.', msguser, appNoticeColor); } } else { cb.sendNotice(noticeOnlyBCMod2, msguser, appNoticeColor); } } else { cb.sendNotice(botName + 'The "/skip" command can only be used if the goals have been successfully started.', msguser, appNoticeColor); } break; } case '/addtips': { if (validGoals) { if (msgisbc || ismodlvlmsg2) { if (commandvar1 == 0 || isNaN(commandvar1)) { cb.sendNotice(botName + 'The parameter is the tip amount to be added to the current tip count, and must be a positive or negative number other than 0. For example, use "/addtips 100" to simulate a user having tipped 100 tokens.',msguser,appNoticeColor); } else if (finalGoalMet) { cb.sendNotice(botName + 'Command cannot be used once all goals, cycles or sequences have been completed.', msguser, appNoticeColor); } else if (commandvar1 < 0 && Math.abs(commandvar1) > currentGoalTips) { cb.sendNotice(botName + 'You cannot subtract more tokens than have been tipped for the current goal.', msguser, appNoticeColor); } else { recordTip(commandvar1,'bc'); if (commandvar1 > 0) { cb.sendNotice(botName + 'You have added ' + commandvar1 + ' tokens.', msguser, appNoticeColor); } else { cb.sendNotice(botName + 'You have subtracted ' + Math.abs(commandvar1) + ' tokens.', msguser, appNoticeColor); } } } else { cb.sendNotice(noticeOnlyBCMod2, msguser, appNoticeColor); } } else { cb.sendNotice(botName + 'The "/addtips" command can only be used if the goals have been successfully started.', msguser, appNoticeColor); } break; } case '/lg': case '/listgoals': { if (validGoals) { if (msgisbc || ismodlvlmsg1) { if (!msgarray[1] || msgarray[1] == 'all') { goalNotices(msgarray[1],msguser,'a','cmd'); } else { cb.sendNotice(botName + 'Invalid parameter provided, the parameter should be left blank to send the list to only the requester, or can be set to "all" to send to the entire room.', msguser, appNoticeColor); } } else { cb.sendNotice(noticeOnlyBCMod1, msguser, appNoticeColor); } } else { cb.sendNotice(botName + 'The "/listgoals" command can only be used if the goals have been successfully started.', msguser, appNoticeColor); } break; } case '/lrg': case '/listremgoals': { if (validGoals) { if (msgisbc || ismodlvlmsg1) { if (!msgarray[1] || msgarray[1] == 'all') { goalNotices(msgarray[1],msguser,'r','cmd'); } else { cb.sendNotice(botName + 'Invalid parameter provided, the parameter should be left blank to send the list to only the requester, or can be set to "all" to send to the entire room.', msguser, appNoticeColor); } } else { cb.sendNotice(noticeOnlyBCMod1, msguser, appNoticeColor); } } else { cb.sendNotice(botName + 'The "/listremgoals" command can only be used if the goals have been successfully started.', msguser, appNoticeColor); } break; } case '/resetapp': { if (validGoals) { if (msgisbc || ismodlvlmsg3) { resetApp(); cb.sendNotice(botName + 'You have reset the App and started the goal show again at the first goal.', msguser, appNoticeColor); } else { cb.sendNotice(noticeOnlyBCMod3, msguser, appNoticeColor); } } else { cb.sendNotice(botName + 'The "/resetapp" command can only be used if the goals have been successfully started.', msguser, appNoticeColor); } break; } case '/paneltext1': case '/paneltext2': case '/paneltext3': { if (msgisbc || ismodlvlmsg2) { var linenum = parseInt(msgarray[0].substring(10)); var paneltext = rawmsg.substring(12).trim(); if (!paneltext) { cb.sendNotice(botName + 'No value was specified for the new panel text line ' + linenum + '.', msguser, appNoticeColor); } else if (!validGoals) { if (linenum == 1) { noAppPanelText1 = paneltext; cb.drawPanel(); cb.sendNotice(botName + 'Panel Line 1 Text has been updated.', msguser, appNoticeColor); } else if (linenum == 2) { noAppPanelText2 = paneltext; cb.drawPanel(); cb.sendNotice(botName + 'Panel Line 2 Text has been updated.', msguser, appNoticeColor); } else if (linenum == 3) { noAppPanelText3 = paneltext; cb.drawPanel(); cb.sendNotice(botName + 'Panel Line 3 Text has been updated.', msguser, appNoticeColor); } cb.drawPanel(); } else { cb.sendNotice(botName + 'The "/paneltext" commands are only for use when goals have not been started, and the app is not set to display Tip Data.', msguser, appNoticeColor); } } else { cb.sendNotice(noticeOnlyBCMod2, msguser, appNoticeColor); } break; } case '/textposn': { if (msgisbc || ismodlvlmsg1) { if (msgarray[1]) { if (msgarray[1] != '0' && msgarray[1] != '1') { cb.sendNotice(botName + 'Invalid parameter value, valid values are "0" for the beginning or "1" for the end of the room title.', msguser, appNoticeColor); } else { if (msgarray[1] == '0') { if (roomTitleTextPosn == 'Before') { cb.sendNotice(botName + 'The User-entered Text position is already set to "Beginning".', msguser, appNoticeColor); } else { roomTitleTextPosn = 'Before'; cb.sendNotice(botName + 'The User-entered Text Position has been updated to "Beginning".', msguser, appNoticeColor); changeRoomSubject(); } } else if (msgarray[1] == '1') { if (roomTitleTextPosn == 'After') { cb.sendNotice(botName + 'The User-entered Text position is already set to "End".', msguser, appNoticeColor); } else { roomTitleTextPosn = 'After'; cb.sendNotice(botName + 'The User-entered Text Position has been updated to "End".', msguser, appNoticeColor); changeRoomSubject(); } } } } else { cb.sendNotice(botName + 'No parameter was specified for the new position, valid values are "0" for the beginning or "1" for the end of the room title.', msguser, appNoticeColor); } } else { cb.sendNotice(noticeOnlyBCMod1, msguser, appNoticeColor); } break; } case '/setmodlevel': { if (msgisbc) { if (msgarray[1]) { if (msgarray[1] != '1' && msgarray[1] != '2' && msgarray[1] != '3') { cb.sendNotice(botName + 'Invalid parameter value, valid values are "1" for "Basic" level, "2" for "Standard" level, or "3" for "Advanced" level. See the "modlevels" help section for more detail (/uahelp modlevels)', msguser, appNoticeColor); } else { if (msgarray[1] == '1') { if (modLevel == 'Basic') { cb.sendNotice(botName + 'The Moderator Trust Level is already set to "Basic".', msguser, appNoticeColor); } else { modLevel = 'Basic'; cb.sendNotice(botName + 'The Moderator Trust Level has been updated to "Basic".', msguser, appNoticeColor); } } else if (msgarray[1] == '2') { if (modLevel == 'Standard') { cb.sendNotice(botName + 'The Moderator Trust Level is already set to "Standard".', msguser, appNoticeColor); } else { modLevel = 'Standard'; cb.sendNotice(botName + 'The Moderator Trust Level has been updated to "Standard".', msguser, appNoticeColor); } } else if (msgarray[1] == '3') { if (modLevel == 'Advanced') { cb.sendNotice(botName + 'The Moderator Trust Level is already set to "Advanced".', msguser, appNoticeColor); } else { modLevel = 'Advanced'; cb.sendNotice(botName + 'The Moderator Trust Level has been updated to "Advanced".', msguser, appNoticeColor); } } } } else { cb.sendNotice(botName + 'No parameter was specified for the new mod trust level, valid values are "1" for "Basic" level, "2" for "Standard" level, or "3" for "Advanced" level. See the "modlevels" help section for more detail (/uahelp modlevels)', msguser, appNoticeColor); } } else { cb.sendNotice(noticeOnlyBC, msguser, appNoticeColor); } break; } //********* Goal Commands case '/restartgoal': { if (validGoals) { if (msgisbc || ismodlvlmsg2) { restartGoal(); cb.sendNotice('You have restarted the current goal.', msguser, appNoticeColor); } else { cb.sendNotice(noticeOnlyBCMod2, msguser, appNoticeColor); } } else { cb.sendNotice('The "/restartgoal" command can only be used if the goals have been successfully started.', msguser, appNoticeColor); } break; } case '/setgoal1': case '/setgoal2': case '/setgoal3': case '/setgoal4': case '/setgoal5': case '/setgoal6': case '/setgoal7': case '/setgoal8': case '/setgoal9': case '/setgoal10': case '/setgoal11': case '/setgoal12': case '/setgoal13': case '/setgoal14': case '/setgoal15': case '/setgoal16': case '/setgoal17': case '/setgoal18': case '/setgoal19': case '/setgoal20': { if (msgisbc || ismodlvlmsg2) { var goalnum = parseInt(msgarray[0].substring(8)); if (commandvar1 <= 0 || isNaN(commandvar1)) { cb.sendNotice('The first parameter is the new amount for goal ' + goalnum + ' and has be be a number greater than 0. For example, "/setgoal' + goalnum + ' 300 Shirt Off" to set goal ' + goalnum + ' to Shirt off at 300 tokens.', msguser, appNoticeColor); } else if (cb.settings.progressiveUpDown == 'Count Up To Goal' && goalnum == currentGoal && commandvar1 <= currentGoalTips) { cb.sendNotice('The current goal cannot be updated to an amount less than what has already been tipped for this goal, or would complete the goal. The "/restartgoal" command can be used to clear the current goal tip totals, but this is not recommended.', msguser, appNoticeColor); } else if (cb.settings.progressiveUpDown == 'Count Down To Zero' && goalnum == currentGoal && commandvar1 <= (currentGoalTotal - currentGoalTips)) { cb.sendNotice('The current goal cannot be updated to an amount less than what has already been tipped for this goal, or would complete the goal. The "/restartgoal" command can be used to clear the current goal tip totals, but this is not recommended.', msguser, appNoticeColor); } else if (!msgarray[2]) { cb.sendNotice('The second parameter is the description of goal ' + goalnum + ' (can be multiple words). For example, "/setgoal' + goalnum + ' 300 Shirt Off" to set goal ' + goalnum + ' to Shirt off at 300 tokens.', msguser, appNoticeColor); } else if (goalnum > 1 && !progGoalArray.amt[goalnum-2] >= 1) { cb.sendNotice('You cannot skip goal levels. If setting a goal for level ' + goalnum + ', then level ' + (goalnum-1) + ' must already have a goal defined.', msguser, appNoticeColor); } else { var goallabel = ''; for (let m6 = 2; m6 < msgarray.length; m6++) { if (m6 == 2) { goallabel = msgarray[m6]; } else { goallabel += ' ' + msgarray[m6]; } } progGoalArray.amt[goalnum-1] = commandvar1; progGoalArray.desc[goalnum-1] = goallabel; if (goalnum == currentGoal) { currentGoalDesc = goallabel; var savcurrenttotal = currentGoalTotal; currentGoalTotal = commandvar1; if (cb.settings.progressiveUpDown == 'Count Down To Zero' && savcurrenttotal != currentGoalTotal) { currentGoalTips = currentGoalTotal - (savcurrenttotal - currentGoalTips); } } if (finalGoalMet == true && goalnum == (currentGoal + 1)) { finalGoalMet = false; if (cb.settings.progressiveUpDown == 'Count Up To Goal') { currentGoalTips = 0; } else { currentGoalTips = currentGoalTotal; } nextGoal(); } else { changeRoomSubject(); } cb.drawPanel(); cb.sendNotice('Goal ' + goalnum + ' was added/updated to the amount of ' + commandvar1 + ' and a description of "' + goallabel + '".', msguser, appNoticeColor); cb.sendNotice(msguser + ' added/updated Progressive Goal #' + goalnum + ' to the goal amount of ' + commandvar1 + ' and a description of "' + goallabel + '".', '', appNoticeColor, '', '', 'red'); cb.sendNotice(msguser + ' added/updated Progressive Goal #' + goalnum + ' to the goal amount of ' + commandvar1 + ' and a description of "' + goallabel + '".', BC, appNoticeColor); } } else { cb.sendNotice(noticeOnlyBCMod2, msguser, appNoticeColor); } break; } case '/goal': { if (validGoals) { if (progressiveAutoNext == 'Select next goal from list') { if (msgisbc || ismodlvlmsg2) { var dogoalnum = msgarray[1]; var dogoalmax = progGoalArray.desc.length; if (!msgarray[1]) { cb.sendNotice('For this command, a parameter is required for the goal selection, and must be a number from 1 to ' + dogoalmax + '.', msguser, appNoticeColor); } else if (isNaN(dogoalnum) || dogoalnum < 1 || dogoalnum > dogoalmax) { cb.sendNotice('The parameter is the goal selection, and must be a number from 1 to ' + dogoalmax + '.', msguser, appNoticeColor); } else if (cb.settings.progressiveUpDown == 'Count Up To Goal' && currentGoalTips > 0 && currentGoalTips < currentGoalTotal) { cb.sendNotice('Command cannot be used during goal, it should be used only to choose the next goal once the current goal is finished. \nThe /skip command can be used to bypass the rest of the current goal.', msguser, appNoticeColor); } else if (cb.settings.progressiveUpDown == 'Count Down To Zero' && currentGoalTips != currentGoalTotal && currentGoalTips > 0) { cb.sendNotice('Command cannot be used during goal, it should be used only to choose the next goal once the current goal is finished. \nThe /skip command can be used to bypass the rest of the current goal.', msguser, appNoticeColor); } else { currentGoal = dogoalnum-1; nextGoal(); cb.drawPanel(); cb.sendNotice('You have started goal #' + currentGoal + ' "' + currentGoalDesc + '".', msguser, appNoticeColor); if (msguser != BC) { cb.sendNotice(msguser + ' has started goal #' + currentGoal + ' "' + currentGoalDesc + '".', BC, appNoticeColor); } } } else { cb.sendNotice(noticeOnlyBCMod2, msguser, appNoticeColor); } } else { cb.sendNotice('The "/goal" command is for use when the goal advance mode is set to "Select next goal from list", and that mode is not enabled.', msguser, appNoticeColor); } } else { cb.sendNotice('The "/goal" command can only be used if the goals have been successfully started.', msguser, appNoticeColor); } break; } case '/rmvgoal': { if (validGoals) { if (msgisbc || ismodlvlmsg2) { var rmvgoalnum = msgarray[1]; if (isNaN(rmvgoalnum) || rmvgoalnum < 1 || rmvgoalnum > 20) { cb.sendNotice('The first parameter is the goal level being removed, and must be a number from 1 to 20 to indicate the goal level number that should be removed. For example, "/rmvgoal 3" will remove the goal and description info for level 3.', msguser, appNoticeColor); } else if (rmvgoalnum > progGoalArray.amt.length) { cb.sendNotice('There is no goal entry at level ' + rmvgoalnum + ', there are currently only entries up to goal level ' + progGoalArray.amt.length + '.', msguser, appNoticeColor); } else { progGoalArray.amt.splice((rmvgoalnum-1),1); progGoalArray.desc.splice((rmvgoalnum-1),1); currentGoalDesc = progGoalArray.desc[currentGoal-1]; currentGoalTotal = progGoalArray.amt[currentGoal-1]; changeRoomSubject(); cb.drawPanel(); cb.sendNotice('Progressive Goal #' + rmvgoalnum + ' was removed from the goal list', msguser, appNoticeColor); cb.sendNotice(msguser + ' removed Progressive Goal #' + rmvgoalnum + ' from the goal list', '', appNoticeColor, '', '', 'red'); cb.sendNotice(msguser + ' removed Progressive Goal #' + rmvgoalnum + ' from the goal list', BC, appNoticeColor); } } else { cb.sendNotice(noticeOnlyBCMod2, msguser, appNoticeColor); } } else { cb.sendNotice('The "/rmvgoal" command can only be used if the goals have been successfully started.', msguser, appNoticeColor); } break; } case '/setgoaltext': { if (validGoals) { if (msgisbc || ismodlvlmsg1) { goalSubjectText = rawmsg.substring(13).trim() if (goalSubjectText != '' && goalSubjectText != null) { changeRoomSubject(); } else { cb.sendNotice('No value was specified for the new Goal Show room subject suffix.', msguser, appNoticeColor); } } else { cb.sendNotice(noticeOnlyBCMod1, msguser, appNoticeColor); } } else { cb.sendNotice('The "/setgoaltxt" command can only be used if the goals have been successfully started.', msguser, appNoticeColor); } break; } //********* Help Menu and Misc case '/emoji': case '/emojis': { if (msgisbc || ismodlvlmsg1) { if (cb.settings.usingFembot == 'No') { let emojimsg = wordWrap('The following is a sample listing of some emojis and unicode characters that can be copied and pasted into the App launch page values for emoji borders or used in other text strings such as a welcome message, goal name, or room title. Note that the room title will not allow some of the more complex emojis so those are separated out in the list.'); emojimsg += '\nRandom 1: \uD83D\uDC45 \uD83D\uDC44 \uD83D\uDC41\uFE0F \uD83D\uDCAA \uD83D\uDC59 \uD83D\uDC60 \uD83D\uDC5C \uD83D\uDCA5 \uD83D\uDCA6 \uD83D\uDECF\uFE0F \uD83E\uDDFB \uD83D\uDEBD \uD83D\uDCFD\uFE0F \uD83D\uDCA1 \uD83D\uDCFA \uD83D\uDD12 \uD83C\uDF0E \u2705 \u274C \u2796 \u2755 \u2754 \u260E\uFE0F'; emojimsg += '\nRandom 2: \uD83D\uDC51 \uD83D\uDD0B \uD83D\uDDA5\uFE0F \uD83C\uDF7D\uFE0F \uD83C\uDF7A \uD83C\uDF78 \uD83E\uDDCA \u2615 \uD83D\uDD95 \uD83D\uDC4F \uD83D\uDE4F \uD83D\uDCEA \uD83D\uDCE7 \u2709\uFE0F \uD83D\uDCB2 \uD83D\uDCB0 \uD83C\uDFB5 \uD83E\uDD41 \uD83C\uDFB8 \uD83C\uDF34 \uD83C\uDF35'; emojimsg += '\nRandom 3: \u2601\uFE0F \uD83D\uDD25 \u26A1 \uD83C\uDF29\uFE0F \uD83C\uDF19 \u2600\uFE0F \u2744\uFE0F \u2B50 \u23F0 \u231B \u231A \uD83D\uDD5B \uD83D\uDEE1\uFE0F \u2694\uFE0F \uD83D\uDDE1\uFE0F \uD83C\uDFF9 \uD83D\uDEA7 \uD83D\uDED1 \u2693'; emojimsg += '\nAnimal Faces: \uD83D\uDE38 \uD83D\uDC3B \uD83D\uDC2E \uD83D\uDC36 \uD83E\uDD81 \uD83D\uDC35 \uD83D\uDC3C \uD83D\uDC37 \uD83E\uDD8A'; emojimsg += '\nAnimals: \uD83D\uDC12 \uD83D\uDC18 \uD83D\uDC04 \uD83E\uDD84 \uD83E\uDD98 \uD83D\uDC1F \uD83D\uDC19 \uD83D\uDC09 \uD83D\uDC22 \uD83E\uDD9E \uD83E\uDD8B \uD83D\uDD77\uFE0F \uD83D\uDD78\uFE0F \uD83D\uDC1E'; emojimsg += '\nFlowers: \uD83C\uDF3C \uD83C\uDF38 \uD83C\uDFF5\uFE0F \uD83C\uDF37 \uD83C\uDF3B'; emojimsg += '\nFood: \uD83C\uDF69 \uD83C\uDF4C \uD83C\uDF52 \uD83C\uDF51 \uD83C\uDF49 \uD83C\uDF53 \uD83E\uDD68 \uD83C\uDF54 \uD83C\uDF2D \uD83C\uDF55 \uD83C\uDF2E \uD83E\uDDC1 \uD83E\uDD55 \uD83C\uDF46 \uD83C\uDF44'; emojimsg += '\nFaces: \uD83D\uDE32 \uD83D\uDE22 \uD83E\uDD21 \uD83D\uDC7D \uD83E\uDD16 \uD83D\uDCA9 \uD83D\uDE0D \uD83D\uDC7F \uD83D\uDC80 \uD83D\uDE44 \uD83D\uDE10 \uD83D\uDE42 \uD83D\uDE07 \uD83D\uDE43'; emojimsg += '\nHearts: \u2764\uFE0F \uD83E\uDDE1 \uD83D\uDC9B \uD83D\uDC9A \uD83D\uDC99 \uD83D\uDC9C \uD83E\uDD0D \uD83D\uDDA4 \uD83D\uDC94'; emojimsg += '\nAwards: \uD83E\uDD47 \uD83E\uDD48 \uD83E\uDD49 \uD83C\uDFC6'; emojimsg += '\nSymbols: \u25AA\uFE0F \u25FE \u25AB\uFE0F \u25FD \uD83D\uDD39 \uD83D\uDD38 \u26D4 \u2622\uFE0F \uD83D\uDEAB \u26A0\uFE0F'; emojimsg += '\nNumbers: 1\uFE0F\u20E3 2\uFE0F\u20E3 3\uFE0F\u20E3 4\uFE0F\u20E3 5\uFE0F\u20E3 6\uFE0F\u20E3 7\uFE0F\u20E3 8\uFE0F\u20E3 9\uFE0F\u20E3 \uD83D\uDD1F'; emojimsg += '\nSports and Gaming: \u265F\uFE0F \u2663\uFE0F \u2665\uFE0F \u2660\uFE0F \uD83C\uDFB0 \uD83C\uDFB1 \uD83D\uDD79\uFE0F \uD83C\uDFAE \u26BE \uD83C\uDFC8 \u26BD'; emojimsg += '\nSeasonal: \u2601\uFE0F \uD83C\uDF84 \u26C4 \uD83C\uDF81 \uD83C\uDF80 \uD83C\uDF85 \uD83C\uDF83 \uD83E\uDD87 \u2618\uFE0F \uD83C\uDF40'; emojimsg += '\nUnicode characters and the following emojis can be used in your room title:'; emojimsg += '\nSample unicode characters: \u2103 \u2109 \u21D0 \u21D1 \u21D2 \u21D3 \u21D4 \u2655 \u265A \u2776 \u2777 \u2778 \u2764 \u2756 \u2749 \u272D \u2740 \u27A4 \uA5BB \uA564 \uA66C \uFFFD'; emojimsg += '\nRoom Title Set 1: \u231B \u2744\uFE0F \u2B50 \u2600\uFE0F \u2764\uFE0F \u26F5 \u26EA \u26A1 \u231A \u26D4 \u2694\uFE0F \u26A0\uFE0F \u26C4 \u2693 \u2618\uFE0F'; emojimsg += '\nRoom Title Set 2: \u2663\uFE0F \u2665\uFE0F \u2660\uFE0F \u25AA\uFE0F \u25FE \u25AB\uFE0F \u25FD \u2615 \u2709\uFE0F 1\uFE0F\u20E3 2\uFE0F\u20E3 3\uFE0F\u20E3 4\uFE0F\u20E3 5\uFE0F\u20E3 6\uFE0F\u20E3 7\uFE0F\u20E3 8\uFE0F\u20E3 9\uFE0F\u20E3'; cb.sendNotice(emojimsg, msguser); } else { cb.sendNotice(botName + 'Since setting "3S" indicates the Fembot is also running, the emojis list is not displayed by this App.', msguser, appNoticeColor); } } else { cb.sendNotice(noticeOnlyBCMod1, msguser, appNoticeColor); } break; } case '/help': { if (msgisbc || ismodlvlmsg1) { let helpcmdtext = 'The Dorothy Apps and Bots each have their own help command, please use one of the following:'; helpcmdtext += '\n/goalhelp - Dorothy\'s Tip Goals (currently running)'; cb.sendNotice(helpcmdtext, msguser, appNoticeColor); } break; } case '/goalshelp': case '/goalhelp': { if (msgisbc || ismodlvlmsg1) { let helptxtmsg = '\u23E9 Dorothys Tip Goals Help Menu for Broadcasters and Moderators \u23EA'; helptxtmsg += '\n \u2705 GENERAL APP USAGE:'; helptxtmsg += '\n \u2022 ' + wordWrap('For the Tip Goal menu, you can setup a single goal, or multiple goals that will be progressed through in sequence as users tip (or you can choose your own goal sequence. There is a configuration flag that defines if the app automatically moves from one goal to the next, or requires the use of the /next command to advance after the goal is met. If set to automatic advance, tips that exceed the goal will carry over to the next goal. If set to advance by command, the tips do not roll over.'); helptxtmsg += '\n \u2022 ' + wordWrap('By default with the "all" setting for Room Title format, the room subject will show 3 things: the current goal amount and description, the next goal description, and a configurable block of text that you can use to define on the launch page to describe the show. You can also enter searchable hashtags to draw more people into the show. This room subject text can be edited using the "/setgoaltext" command as noted below.'); helptxtmsg += '\n \u2022 ' + wordWrap('Any changes you make using commands during the show are not stored permanently, they are only stored within the current session. They will be kept if you switch between app features, but not if you deactivate the app. '); helptxtmsg += '\n \u2022 ' + wordWrap('There are lots of options for personalization, including notice color themes, panel backgrounds and text colors, notice borders, welcome messages, goal descriptions, room titles format, and more. Make sure to check out section 3 on the launch page'); helptxtmsg += '\n \u2705 GOAL COMMANDS:'; helptxtmsg += '\n \u2022 ' + wordWrap('/setgoal1, /setgoal2, /setgoal3...(thru /setgoal20) [goal] [description] : These are the commands that let you edit the goals for your show. Both the [goal] and [description] parameters must be entered every time and will update both values. Note this is also only a temporary change made within the session, it does not permanently update the launch page config.'); helptxtmsg += '\n \u2022 ' + wordWrap('--- The 1-20 designation as part of the command identifies which entry you are modifying.'); helptxtmsg += '\n \u2022 ' + wordWrap('--- The [goal] parameter is the new value you are setting for the goal amount. Even if you are not changing the goal (only changing the description, you must still enter the existing value for the goal.'); helptxtmsg += '\n \u2022 ' + wordWrap('--- The [description] Parameter is the new value you are setting for the goal description. Even if you are not changing the description (only changing the goal amount), you must still enter the existing value for the description.'); helptxtmsg += '\n \u2022 ' + wordWrap('--- An example of the syntax for this command would be "/setgoal4 400 Blow job", which would set goal 4 to be a Blow Job once you reach 400 tokens. '); helptxtmsg += '\n \u2022 ' + wordWrap('--- Note that you can\'t make updates to the current goal or past goal, only future goals.'); helptxtmsg += '\n \u2022 ' + wordWrap('/rmvgoal [level] : Remove the goal entry for goal level of [level] (amount and description are both removed). Note this is also only a temporary change made within the session, it does not permanently update the launch page config.'); helptxtmsg += '\n \u2022 ' + wordWrap('/goal [goal] : Used to manually select the next [goal] once the current goal is complete, when auto advance is turned off. You can choose a new goal or one that was already completed.'); helptxtmsg += '\n \u2022 ' + wordWrap('/next : Used to advance to the next goal once the current goal is complete, when you have configured "Select the next goal".'); helptxtmsg += '\n \u2022 ' + wordWrap('/skip : Advance to the next goal regardless of the status of the current goal.'); helptxtmsg += '\n \u2022 ' + wordWrap('/addtips [tokens] : Within the goal apps (Progressive Goal, Goal Count, and Tip Jar), this can be used to simulate users having tipped and advance the token count within a goal. Indicate the number of tokens you are adding as the [tokens] parameter, and note the value can be negative. You can add more than the current goal, but you cannot subtract less than has been tipped in the current goal.'); helptxtmsg += '\n \u2022 ' + wordWrap('/listgoals (also /lg) : List the current setup of all goals for the App feature that is active. You can add the "all" parameter to display to the entire chat ("/lg all" for example).'); helptxtmsg += '\n \u2022 ' + wordWrap('/listremgoals (also /lrg) : List the current setup of the remaining goals for the App feature that is active. You can add the "all" parameter to display to the entire chat ("/lrg all" for example).'); helptxtmsg += '\n \u2022 ' + wordWrap('/restartgoal : If you\'d like to repeat a goal (common if you have a single goal you\'re recycling), you can use this command at any time to reset the tip count on the current goal to 0 (even if already complete)'); helptxtmsg += '\n \u2705 ADDITIONAL COMMANDS:'; helptxtmsg += '\n \u2022 ' + wordWrap('/chgpanelbg [imagename]: Change the background of the drawpanel to one of the valid images. Images are updated regularly, so you can see the current list by entering this command with no parameter (/chgpanelbg) and the resulting notice message will show the current valid choices. Note that you can also see the images by going to the "Source Code" tab for the app and clicking the link for "View App Images".'); helptxtmsg += '\n \u2022 ' + wordWrap('/paneltextcolor [newcolor]: Change the color of the text in the drawpanel to either a hex code (#0000ff) or the exact text of one of the color choices from the menu ("Dark Green", "Dark Red", etc). You can lookup hex codes for any color on a site such as Color-hexa: https://www.colorhexa.com/'); helptxtmsg += '\n \u2022 ' + wordWrap('/setroomtext [newtext]: Update the user-entered text that is part of the Room Title.'); helptxtmsg += '\n \u2022 ' + wordWrap('/textposn [0 or 1]: Update the default setting for whether the User-emtered Text is shown before or after the Current Goal and Next Goal text.'); helptxtmsg += '\n \u2022 ' + wordWrap('/paneltext1 [newtext] (also /paneltext2, /paneltext3): When there are not valid goals running, change the text displayed in the draw panel, separate commands for lines 1-3, max of 50 characters each. If an app is running but completed, can change to no app running with "/chgapp none".'); helptxtmsg += '\n \u2022 ' + wordWrap('/setmodlevel [1,2 or 3]: Update the mod trust level. 1=Basic, 2=Standard, 3=Advanced. See the "modlevels" help section for more detail.'); helptxtmsg += '\n \u2022 ' + wordWrap('** You can also type "/about" or "/modlevels" to see additional help information on those topics'); cb.sendNotice(helptxtmsg, msguser, appNoticeColor); } else { cb.sendNotice(noticeOnlyBCMod1, msguser, appNoticeColor); } break; } case '/about': { let aboutmessage = '\u23E9 Dorothy\'s Tip Goals \u23EA'; aboutmessage += '\n \u2705 About the App:'; aboutmessage += '\n \u2022 Version 2.1 was released April 8, 2021, written by CB users chelsea2950 and butter_my_toast.'; aboutmessage += '\n \u2022 \u2757 \u2757 \u2757 ' + wordWrap('Please note that version 2.0 was a complete upgrade of the Tip Goals App to align with the Progressive Goal feature of Dorothy\'s UltraApp'); aboutmessage += '\n \u2022 \u2757 \u2757 \u2757 ' + wordWrap('Please review your settings to ensure they are set appropriately for your show.'); aboutmessage += '\n \u2022 ' + wordWrap('Goals and the Show description should not have changed, but there are a lot of new fetures and the launch page has been reorganized.'); aboutmessage += '\n \u2022 ' + wordWrap('Comments, suggestions, requests, and bug reports can be made by either tweeting @thechelsea2950, or by posting comments on bot help page.'); aboutmessage += '\n \u2022 You can type "/goalhelp" to display the command list summary'; aboutmessage += '\n \u2022 ' + wordWrap('The app description page includes extensive details on App features, moderator trust levels, commands and recent release notes:'); aboutmessage += '\n https://chaturbate.com/apps/app_details/dorothys-tip-goals/ '; aboutmessage += '\n\n \u2705 Highlights of fixes and improvements for version 2.1:'; aboutmessage += '\n \u2022 Update the notice borders to be better aligned'; aboutmessage += '\n \u2022 ' + wordWrap('Update "help" and "about" text, and places where long goals may be displayed to have word wrap functions'); aboutmessage += '\n \u2022 Default to color theme of "Shades of Blue"'; aboutmessage += '\n \u2022 ' + wordWrap('Rearrange and group the settings in section 3 for personalization, remove redundant color settings, don\'t need Tip Goals color setting + theme since only one feature in this app'); cb.sendNotice(aboutmessage, msguser, appNoticeColor); break; } case '/modlevels': { let modlevelmsg = '\u23E9 Dorothy\'s Tip Goals - Moderator Trust levels \u23EA'; modlevelmsg += '\n \u2705 "Basic" Moderator Abilities'; modlevelmsg += '\n \u2022 Use the List Goals and List Remaining Goals commands'; modlevelmsg += '\n \u2022 Update the room title and other goal related text'; modlevelmsg += '\n \u2022 Display the emoji list'; modlevelmsg += '\n \u2022 Access the moderator help page'; modlevelmsg += '\n \u2705 "Standard" Moderator Abilities'; modlevelmsg += '\n \u2022 All "Basic" ablities plus the below'; modlevelmsg += '\n \u2022 Edit and maintain goals, restart a goal'; modlevelmsg += '\n \u2022 Update the panel background and text color'; modlevelmsg += '\n \u2022 Update the theme color (background and text)'; modlevelmsg += '\n \u2022 Skip and manually advance goals'; modlevelmsg += '\n \u2022 Manually add tips to a goal'; modlevelmsg += '\n \u2705 "Advanced" Moderator Abilities'; modlevelmsg += '\n \u2022 All "Standard" ablities plus the below'; modlevelmsg += '\n \u2022 Reset the current app feature and start over'; modlevelmsg += '\n \u2705 ' + wordWrap('Only the broadcaster can use the /setmodlevel command to update the moderator trust level setting during the show.'); cb.sendNotice(modlevelmsg, msguser, appNoticeColor); break; } } } return msg; }); // **************************** Actions on user entering ***************************** cb.onEnter(function(user) { var enteruser = user.user; var enterismod = user.is_mod; var enterisbc = (enteruser === BC); var enterisnotgray = user.has_tokens; if (cb.settings.enableEntryMessage == 'Yes' && !enterisbc && enterisnotgray) { if (cb.settings.entryMessage) { var entrywelcomemsg = borderWelcomeTop; entrywelcomemsg += '\n' + checkNextLine(checkUsername(cb.settings.entryMessage,enteruser)); if (cb.settings.noticeSepStyle != 'No Border') { entrywelcomemsg += '\n' + borderWelcomeBottom; } cb.sendNotice(entrywelcomemsg, enteruser, progGoalBgColor, progGoalTextColor, 'bold'); } if (validGoals) { goalNotices(enteruser,enteruser,'r','entry'); } } }); // *********************************** Actions upon leaving ************************************** cb.onLeave(function(user) { var leaveuser = user.user; }); // *********************************** Actions upon Draw Panel ************************************** cb.onDrawPanel(function (user) { var panel = {}; if (botPanel) { panel.template = 'image_template'; panel.row1_label = "row1_label"; panel.row1_value = "row1_value"; panel.row2_label = "row2_label"; panel.row2_value = "row2_value"; panel.row3_label = "row3_label"; panel.row3_value = "row3_value"; } else { panel.template = '3_rows_11_21_31'; } if (validGoals) { if (!finalGoalMet) { if (cb.settings.progressiveUpDown == 'Count Up To Goal') { panel.row1_value = 'Current Goal (#' + (currentGoal) + ') : ' + (currentGoalTips > currentGoalTotal ? currentGoalTotal : currentGoalTips) + ' / ' + currentGoalTotal + ' \u25FE (' + (currentGoalTotal-(currentGoalTips > currentGoalTotal ? currentGoalTotal : currentGoalTips)) + ' left)'; leftjust1 = leftJustify(panel.row1_value,1); panel.row2_value = 'Progress: ' + goalBar((currentGoalTips > currentGoalTotal ? currentGoalTotal : currentGoalTips),currentGoalTotal) + ' (' + Math.floor((currentGoalTips > currentGoalTotal ? currentGoalTotal : currentGoalTips)/currentGoalTotal*100) + ')'; leftjust2 = 999; if (cb.settings.showTotals == 'Yes') { panel.row3_value = 'Total Goal Show Tips: ' + currentAppTotalGoal; } else { panel.row3_value = 'At Goal: ' + currentGoalDesc; } leftjust3 = leftJustify(panel.row3_value,3); } else { panel.row1_value = 'To Goal: ' + (currentGoalTips <= 0 ? '0 \u25FE Goal Reached!' : currentGoalTips + ' \u25FE Countdown to 0') ; leftjust1 = leftJustify(panel.row1_value,1); panel.row2_value = 'Progress: ' + goalBar((currentGoalTips <= 0 ? currentGoalTotal : (currentGoalTotal-currentGoalTips)),currentGoalTotal) + ' (' + Math.floor((currentGoalTips <= 0 ? currentGoalTotal : (currentGoalTotal-currentGoalTips))/currentGoalTotal*100) + ' )'; leftjust2 =42; if (cb.settings.showTotals == 'Yes') { panel.row3_value = 'Total Goal Show Tips: ' + currentAppTotalGoal; } else { panel.row3_value = 'At Goal: ' + currentGoalDesc; } leftjust3 = leftJustify(panel.row3_value,3); } } else { panel.row1_value = 'All Goals Completed!'; leftjust1 = leftJustify(panel.row1_value,1); panel.row2_value = 'Progress: ' + goalBar(100,100) + ' (100 %)'; leftjust2 = 999; if (cb.settings.showTotals == 'Yes') { panel.row3_value = 'Total Goal Show Tips: ' + currentAppTotalGoal; } else { panel.row3_value = ''; } leftjust3 = leftJustify(panel.row3_value,3); } } else { if (cb.settings.noAppRunningDisplay == 'Welcome to my room') { panel.row1_value = noAppPanelText1; leftjust1 = leftJustify(panel.row1_value,1); panel.row2_value = noAppPanelText2; leftjust2 = leftJustify(panel.row2_value,2); panel.row3_value = noAppPanelText3; leftjust3 = leftJustify(panel.row3_value,3); } else { panel.row1_value = 'Highest Tip: ' + highestTipper + ' (' + highestTip + ')'; leftjust1 = leftJustify(panel.row1_value,1); panel.row2_value = 'Most Recent Tip: ' + mostRecentTipper + ' (' + mostRecentTip + ')'; leftjust2 = leftJustify(panel.row2_value,2); if (cb.settings.showTotals == 'Yes') { panel.row3_value = 'Total Show Tips: ' + currentSessionTotal; } else { panel.row3_value = 'Number of Unique Tippers: ' + tipCountArray.name.length; } leftjust3 = leftJustify(panel.row3_value,3); } } panel.layers = [ {'type': 'image', 'fileID': backgroundImage}, { 'type': 'text', 'text': panel.row1_value, 'top': topjust1, 'left': leftjust1, 'font-size': fontSize, 'font-weight': 'bold', 'color': textColor, }, { 'type': 'text', 'text': panel.row2_value, 'top': topjust2, 'left': leftjust2, 'font-size': fontSize, 'color': textColor, }, { 'type': 'text', 'text': panel.row3_value, 'top': topjust3, 'left': leftjust3, 'font-size': fontSize, 'color': textColor, }, ] return panel; }); // *********************************** Actions upon tipping ************************************** cb.onTip (function (tip) { var tipamount = Number.parseInt(tip.amount, 10); var tipnote = tip.message; var tipfromuser = tip.from_user var tipisanon = tip.is_anon_tip; var tipfromdisplayuser = tipfromuser; // ***** Tip Count Array if (tipisanon) { tipfromdisplayuser = 'Anonymous User'; } else { if (!cbjs.arrayContains(tipCountArray.name, tipfromuser)) { tipCountArray.name.push(tipfromuser); tipCountArray.amount.push(tipamount); } else { tipCountArray.amount[findTipper(tipfromuser)] += tipamount; } } if (tipamount >= highestTip) { highestTip = tipamount; highestTipper = tipfromdisplayuser; } mostRecentTip = tipamount; mostRecentTipper = tipfromdisplayuser; // ***** Record tip for goal progress and track total stats recordTip(tipamount,tipfromuser); });
© Copyright Chaturbate 2011- 2024. All Rights Reserved.