Apps Home
|
Create an App
Elifeytest
Author:
prettynoize
Description
Source Code
Launch App
Current Users
Created by:
Prettynoize
/* * ========================================================== * ELIFEY BOT v1.0 * Personal tip menu + goal + notices + user personalization * ========================================================== */ var BOT_NAME = "ELIFEY BOT"; var VERSION = "1.0"; /* ========================================================== SETTINGS ========================================================== */ cb.settings_choices = [ // ---------- LOOK ---------- { name: "main_color", type: "str", label: "LOOK • Main HEX color", defaultValue: "#D8B4C8", minLength: 6, maxLength: 7 }, { name: "text_color", type: "str", label: "LOOK • Text HEX color", defaultValue: "#382E31", minLength: 6, maxLength: 7 }, { name: "symbol", type: "str", label: "LOOK • Main symbol", defaultValue: "♡", maxLength: 20 }, // ---------- ABOUT ---------- { name: "about_text", type: "str", label: "ABOUT • Text shown with /about", defaultValue: "hi, i'm elifey ♡ i sing, draw and make strange little things.", maxLength: 500 }, // ---------- GOAL ---------- { name: "goal_enabled", type: "choice", label: "GOAL • Enable goal?", choice1: "Yes", choice2: "No", defaultValue: "Yes" }, { name: "goal_amount", type: "int", label: "GOAL • Goal amount", minValue: 1, defaultValue: 500 }, { name: "goal_name", type: "str", label: "GOAL • Goal name", defaultValue: "little stream goal", maxLength: 200 }, // ---------- TIP MENU ---------- { name: "menu_enabled", type: "choice", label: "MENU • Enable tip menu?", choice1: "Yes", choice2: "No", defaultValue: "Yes" }, { name: "item1_name", type: "str", label: "MENU 1 • Name", defaultValue: "draw something", required: false }, { name: "item1_price", type: "int", label: "MENU 1 • Tokens", defaultValue: 25, minValue: 1 }, { name: "item2_name", type: "str", label: "MENU 2 • Name", defaultValue: "choose a song", required: false }, { name: "item2_price", type: "int", label: "MENU 2 • Tokens", defaultValue: 40, minValue: 1 }, { name: "item3_name", type: "str", label: "MENU 3 • Name", defaultValue: "choose my look", required: false }, { name: "item3_price", type: "int", label: "MENU 3 • Tokens", defaultValue: 55, minValue: 1 }, { name: "item4_name", type: "str", label: "MENU 4 • Name", defaultValue: "little dance", required: false }, { name: "item4_price", type: "int", label: "MENU 4 • Tokens", defaultValue: 75, minValue: 1 }, { name: "item5_name", type: "str", label: "MENU 5 • Name", defaultValue: "choose what i draw", required: false }, { name: "item5_price", type: "int", label: "MENU 5 • Tokens", defaultValue: 100, minValue: 1 }, // ---------- NOTICES ---------- { name: "notices_enabled", type: "choice", label: "NOTICES • Enable rotating notices?", choice1: "Yes", choice2: "No", defaultValue: "Yes" }, { name: "notice_interval", type: "int", label: "NOTICES • Interval in minutes", minValue: 2, maxValue: 60, defaultValue: 8 }, { name: "notice1", type: "str", label: "NOTICE 1", defaultValue: "new here? type /about", required: false }, { name: "notice2", type: "str", label: "NOTICE 2", defaultValue: "tip menu → /menu", required: false }, { name: "notice3", type: "str", label: "NOTICE 3", defaultValue: "follow if you want to find me again ♡", required: false }, // ---------- PERSONALIZATION ---------- { name: "personalization", type: "choice", label: "PERSONALIZATION • Enable tip reactions?", choice1: "Yes", choice2: "No", defaultValue: "Yes" }, { name: "familiar_amount", type: "int", label: "PERSONALIZATION • Familiar face at total tokens", defaultValue: 100, minValue: 1 }, { name: "favorite_amount", type: "int", label: "PERSONALIZATION • Favorite at total tokens", defaultValue: 300, minValue: 1 }, { name: "menace_amount", type: "int", label: "PERSONALIZATION • Little menace at total tokens", defaultValue: 700, minValue: 1 } ]; /* ========================================================== STATE ========================================================== */ var state = { goalCurrent: 0, goalTarget: 0, goalName: "", menuEnabled: true, noticesEnabled: true, totalTokens: 0, totalTips: 0, users: {}, topUser: null, topTotal: 0, noticeIndex: 0, goalCompleted: false }; /* ========================================================== HELPERS ========================================================== */ function validHex(value, fallback) { value = String(value || "").trim(); if (value.charAt(0) !== "#") { value = "#" + value; } if (/^#[0-9A-Fa-f]{6}$/.test(value)) { return value; } return fallback; } function mainColor() { return validHex(cb.settings.main_color, "#D8B4C8"); } function textColor() { return validHex(cb.settings.text_color, "#382E31"); } function symbol() { return cb.settings.symbol || "♡"; } function privateNotice(text, user) { cb.sendNotice( text, user, "", mainColor(), "bold" ); } function publicNotice(text) { cb.sendNotice( text, "", "", mainColor(), "bold" ); } function ownerNotice(text) { privateNotice(text, cb.room_slug); } function cleanUsername(username) { return String(username || "someone"); } function progressBar(current, target) { var blocks = 10; if (target <= 0) { return "░░░░░░░░░░"; } var ratio = current / target; if (ratio > 1) ratio = 1; if (ratio < 0) ratio = 0; var filled = Math.floor(ratio * blocks); var output = ""; for (var i = 0; i < blocks; i++) { output += i < filled ? "█" : "░"; } return output; } /* ========================================================== MENU ========================================================== */ function getMenuItems() { var items = []; for (var i = 1; i <= 5; i++) { var name = cb.settings["item" + i + "_name"]; var price = parseInt(cb.settings["item" + i + "_price"], 10); if ( name && String(name).trim() !== "" && price > 0 ) { items.push({ name: String(name).trim(), price: price }); } } return items; } function menuText() { if (!state.menuEnabled) { return symbol() + " tip menu is currently off"; } var items = getMenuItems(); if (!items.length) { return symbol() + " tip menu is empty"; } var lines = [ symbol() + " ELIFEY TIP MENU" ]; for (var i = 0; i < items.length; i++) { lines.push( symbol() + " " + items[i].name + " — " + items[i].price + " tk" ); } return lines.join("\n"); } function findMenuItem(amount) { if (!state.menuEnabled) return null; var items = getMenuItems(); for (var i = 0; i < items.length; i++) { if (items[i].price === amount) { return items[i]; } } return null; } /* ========================================================== GOAL ========================================================== */ function goalText() { if (cb.settings.goal_enabled !== "Yes") { return symbol() + " no active goal right now"; } return ( symbol() + " " + state.goalName + "\n" + progressBar(state.goalCurrent, state.goalTarget) + " " + state.goalCurrent + " / " + state.goalTarget + " tk" ); } function checkGoal() { if ( cb.settings.goal_enabled === "Yes" && !state.goalCompleted && state.goalCurrent >= state.goalTarget ) { state.goalCompleted = true; publicNotice( symbol() + " goal reached: " + state.goalName + " ♡" ); } } /* ========================================================== USER PERSONALIZATION ========================================================== */ function ensureUser(username) { if (!state.users[username]) { state.users[username] = { total: 0, tips: 0, level: "visitor" }; } return state.users[username]; } function getLevel(total) { if (total >= parseInt(cb.settings.menace_amount, 10)) { return "little menace"; } if (total >= parseInt(cb.settings.favorite_amount, 10)) { return "favorite"; } if (total >= parseInt(cb.settings.familiar_amount, 10)) { return "familiar face"; } return "visitor"; } function personalizedReaction(username, user, oldLevel) { if (cb.settings.personalization !== "Yes") { return; } var newLevel = user.level; if (oldLevel !== newLevel) { if (newLevel === "familiar face") { publicNotice( symbol() + " " + username + " is officially a familiar face" ); } else if (newLevel === "favorite") { publicNotice( symbol() + " " + username + " has become one of my favorites" ); } else if (newLevel === "little menace") { publicNotice( symbol() + " " + username + " is officially a little menace" ); } } } /* ========================================================== TIPS ========================================================== */ cb.onTip(function(tip) { var amount = parseInt(tip.amount, 10); var username = cleanUsername(tip.from_user); if (!amount || amount <= 0) { return; } state.totalTokens += amount; state.totalTips += 1; /* USER */ var user = ensureUser(username); var oldLevel = user.level; user.total += amount; user.tips += 1; user.level = getLevel(user.total); /* TOP TIPPER */ if (user.total > state.topTotal) { state.topTotal = user.total; state.topUser = username; } /* GOAL */ if (cb.settings.goal_enabled === "Yes") { state.goalCurrent += amount; checkGoal(); } /* MENU MATCH */ var item = findMenuItem(amount); if (item) { publicNotice( symbol() + " " + username + " chose: " + item.name + " ♡" ); } /* FIRST TIP */ if ( cb.settings.personalization === "Yes" && user.tips === 1 ) { privateNotice( symbol() + " thank you for your first tip, " + username + " ♡", username ); } personalizedReaction( username, user, oldLevel ); cb.drawPanel(); }); /* ========================================================== NOTICES ========================================================== */ function getNotices() { var notices = []; for (var i = 1; i <= 3; i++) { var text = cb.settings["notice" + i]; if ( text && String(text).trim() !== "" ) { notices.push(String(text).trim()); } } return notices; } function rotateNotice() { if (state.noticesEnabled) { var notices = getNotices(); if (notices.length) { if (state.noticeIndex >= notices.length) { state.noticeIndex = 0; } publicNotice( symbol() + " " + notices[state.noticeIndex] ); state.noticeIndex++; } } var minutes = parseInt( cb.settings.notice_interval, 10 ); if (!minutes || minutes < 2) { minutes = 8; } cb.setTimeout( rotateNotice, minutes * 60000 ); } /* ========================================================== COMMANDS ========================================================== */ function showHelp(user) { var text = symbol() + " ELIFEY BOT\n\n" + "/menu — tip menu\n" + "/goal — current goal\n" + "/about — about me\n" + "/top — top supporter\n" + "/mystats — your support stats\n" + "/help — commands"; privateNotice(text, user); } function showOwnerHelp() { ownerNotice( symbol() + " ELIFEY BOT • OWNER\n\n" + "/menuon\n" + "/menuoff\n\n" + "/noticeon\n" + "/noticeoff\n\n" + "/setgoal 500 goal name\n" + "/goalreset\n\n" + "/stats\n" + "/debug" ); } function showStats() { var top = state.topUser ? state.topUser + " (" + state.topTotal + " tk)" : "none"; ownerNotice( symbol() + " STREAM STATS\n\n" + "tokens: " + state.totalTokens + "\n" + "tips: " + state.totalTips + "\n" + "unique tippers: " + Object.keys(state.users).length + "\n" + "top: " + top ); } function showDebug() { ownerNotice( symbol() + " ELIFEY DEBUG\n\n" + "version: " + VERSION + "\n" + "goal: " + state.goalCurrent + "/" + state.goalTarget + "\n" + "goal completed: " + state.goalCompleted + "\n" + "menu: " + state.menuEnabled + "\n" + "notices: " + state.noticesEnabled + "\n" + "users tracked: " + Object.keys(state.users).length + "\n" + "main HEX: " + mainColor() ); } /* ========================================================== MESSAGE HANDLER ========================================================== */ cb.onMessage(function(msg) { var message = String(msg.m || "").trim(); var command = message.toLowerCase(); var username = msg.user; var isOwner = username === cb.room_slug; /* Not a command */ if (message.charAt(0) !== "/") { return msg; } /* PUBLIC COMMANDS */ if (command === "/menu") { privateNotice( menuText(), username ); msg["X-Spam"] = true; return msg; } if (command === "/goal") { privateNotice( goalText(), username ); msg["X-Spam"] = true; return msg; } if (command === "/about") { privateNotice( symbol() + " " + cb.settings.about_text, username ); msg["X-Spam"] = true; return msg; } if (command === "/top") { var topText = state.topUser ? symbol() + " top supporter: " + state.topUser + " — " + state.topTotal + " tk" : symbol() + " no top supporter yet"; privateNotice( topText, username ); msg["X-Spam"] = true; return msg; } if (command === "/mystats") { var user = state.users[username]; if (!user) { privateNotice( symbol() + " no tips tracked for you yet", username ); } else { privateNotice( symbol() + " YOUR STATS\n\n" + "total: " + user.total + " tk\n" + "tips: " + user.tips + "\n" + "status: " + user.level, username ); } msg["X-Spam"] = true; return msg; } if (command === "/help") { showHelp(username); if (isOwner) { showOwnerHelp(); } msg["X-Spam"] = true; return msg; } /* OWNER ONLY FROM HERE */ if (!isOwner) { if ( command === "/menuon" || command === "/menuoff" || command === "/noticeon" || command === "/noticeoff" || command === "/goalreset" || command === "/stats" || command === "/debug" || command.indexOf("/setgoal ") === 0 ) { privateNotice( symbol() + " broadcaster only", username ); msg["X-Spam"] = true; } return msg; } if (command === "/menuon") { state.menuEnabled = true; ownerNotice( symbol() + " tip menu ON" ); } else if (command === "/menuoff") { state.menuEnabled = false; ownerNotice( symbol() + " tip menu OFF" ); } else if (command === "/noticeon") { state.noticesEnabled = true; ownerNotice( symbol() + " notices ON" ); } else if (command === "/noticeoff") { state.noticesEnabled = false; ownerNotice( symbol() + " notices OFF" ); } else if (command === "/goalreset") { state.goalCurrent = 0; state.goalCompleted = false; ownerNotice( symbol() + " goal reset" ); cb.drawPanel(); } else if (command.indexOf("/setgoal ") === 0) { var parts = message.split(/\s+/); if (parts.length < 3) { ownerNotice( "Use: /setgoal 500 goal name" ); } else { var target = parseInt(parts[1], 10); if (!target || target < 1) { ownerNotice( "Goal must be a number above 0." ); } else { var name = parts.slice(2).join(" "); state.goalTarget = target; state.goalName = name; state.goalCurrent = 0; state.goalCompleted = false; ownerNotice( symbol() + " new goal: " + name + " — " + target + " tk" ); cb.drawPanel(); } } } else if (command === "/stats") { showStats(); } else if (command === "/debug") { showDebug(); } else { return msg; } msg["X-Spam"] = true; return msg; }); /* ========================================================== PANEL ========================================================== */ cb.onDrawPanel(function(user) { var top = state.topUser ? state.topUser + " • " + state.topTotal + " tk" : "—"; return { template: "3_rows_of_labels", row1_label: "♡ GOAL", row1_value: state.goalCurrent + " / " + state.goalTarget, row2_label: "♡ TOP", row2_value: top, row3_label: "♡ COMMANDS", row3_value: "/menu • /goal • /about" }; }); /* ========================================================== INIT ========================================================== */ function init() { state.goalTarget = parseInt( cb.settings.goal_amount, 10 ) || 500; state.goalName = cb.settings.goal_name || "little stream goal"; state.menuEnabled = cb.settings.menu_enabled === "Yes"; state.noticesEnabled = cb.settings.notices_enabled === "Yes"; cb.drawPanel(); ownerNotice( symbol() + " " + BOT_NAME + " v" + VERSION + " started\n\n" + "Type /help for commands." ); var minutes = parseInt( cb.settings.notice_interval, 10 ); if (!minutes || minutes < 2) { minutes = 8; } cb.setTimeout( rotateNotice, minutes * 60000 ); } init();
© Copyright Chaturbate 2011- 2026. All Rights Reserved.