// ==UserScript==
// @name Addon + for Bodega Bot
// @namespace http://tampermonkey.net/
// @version 2.0
// @description Adds functionality to Bodega Bot Users
// @author Bort
// @license
// @icon https://media1.giphy.com/avatars/FeedMe1219/aBrdzB77IQ5c.gif
// @match https://tinychat.com/room/*
// @match https://tinychat.com/*
// @exclude https://tinychat.com/settings/*
// @exclude https://tinychat.com/subscription/*
// @exclude https://tinychat.com/promote/*
// @exclude https://tinychat.com/coins/*
// @exclude https://tinychat.com/gifts*
// @grant GM_setClipboard
// @require https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js
// ==/UserScript==
(function() {
'use strict';
// Create container for the floating button
const container = document.createElement('div');
container.style.position = 'fixed';
container.style.width = '100%';
container.style.height = '100%';
container.style.top = '0';
container.style.left = '0';
container.style.zIndex = '9999';
container.style.pointerEvents = 'none';
document.body.appendChild(container);
// Create main floating button
const mainButton = document.createElement('button');
mainButton.className = 'floating-button';
mainButton.innerText = '⚙️';
mainButton.title = 'Open Settings';
mainButton.style.position = 'fixed';
mainButton.style.bottom = '20px';
mainButton.style.left = '20px';
mainButton.style.width = '40px';
mainButton.style.height = '40px';
mainButton.style.backgroundColor = 'rgb(0 0 0 / 20%)';
mainButton.style.color = 'white';
mainButton.style.border = 'none';
mainButton.style.borderRadius = '50%';
mainButton.style.cursor = 'pointer';
mainButton.style.transition = 'all 0.3s';
mainButton.style.zIndex = '10000';
mainButton.style.fontSize = '20px';
mainButton.style.display = 'flex';
mainButton.style.alignItems = 'center';
mainButton.style.justifyContent = 'center';
mainButton.style.pointerEvents = 'auto';
container.appendChild(mainButton);
// Create container for additional buttons
const additionalButtons = document.createElement('div');
additionalButtons.className = 'additional-buttons';
additionalButtons.style.display = 'none';
additionalButtons.style.flexDirection = 'column';
additionalButtons.style.position = 'fixed';
additionalButtons.style.left = '20px';
additionalButtons.style.bottom = '70px';
additionalButtons.style.zIndex = '10001';
additionalButtons.style.pointerEvents = 'auto';
container.appendChild(additionalButtons);
// Array of additional button configurations
const buttonConfigs = [
{ label: '📷', action: takeScreenshot, title: 'Take Screenshot' },
{ label: '📺', action: toggleGroupTube, title: 'Toggle GroupTube' },
{ label: '🔍+', action: () => resizeGroupTube(1.1), title: 'Increase GroupTube Size' },
{ label: '🔍-', action: () => resizeGroupTube(0.9), title: 'Decrease GroupTube Size' },
{ label: '🔄', action: reloadGroupTube, title: 'Reload GroupTube' },
{ label: '📝', action: showCommands, title: 'Show Commands' }
];
// Create additional buttons
buttonConfigs.forEach(config => {
const button = document.createElement('button');
button.className = 'additional-button';
button.innerText = config.label;
button.title = config.title;
button.style.backgroundColor = 'rgb(0 0 0 / 20%)';
button.style.color = 'white';
button.style.border = 'none';
button.style.margin = '5px';
button.style.padding = '10px';
button.style.borderRadius = '5px';
button.style.cursor = 'pointer';
button.style.transition = 'all 0.3s';
button.style.width = '40px';
button.style.height = '40px';
button.style.fontSize = '16px';
button.style.display = 'flex';
button.style.alignItems = 'center';
button.style.justifyContent = 'center';
additionalButtons.appendChild(button);
// Add click event listener
button.addEventListener('click', () => {
config.action();
// Provide visual feedback
const originalColor = button.style.backgroundColor;
button.style.backgroundColor = 'rgb(0 0 0 / 20%)';
setTimeout(() => {
button.style.backgroundColor = originalColor;
}, 200);
});
// Hover effect for additional buttons
button.addEventListener('mouseover', () => {
button.style.backgroundColor = 'rgb(0 0 0 / 30%)';
});
button.addEventListener('mouseout', () => {
button.style.backgroundColor = 'rgb(0 0 0 / 20%)';
});
});
// Toggle additional buttons display on main button click
mainButton.addEventListener('click', function() {
const isExpanded = additionalButtons.style.display === 'flex';
additionalButtons.style.display = isExpanded ? 'none' : 'flex';
mainButton.style.transform = isExpanded ? 'rotate(0deg)' : 'rotate(180deg)';
});
// Allow dragging of the main button
let isDraggingMain = false;
let mainOffsetX, mainOffsetY;
mainButton.addEventListener('mousedown', (e) => {
isDraggingMain = true;
mainOffsetX = e.clientX - mainButton.getBoundingClientRect().left;
mainOffsetY = e.clientY - mainButton.getBoundingClientRect().top;
});
document.addEventListener('mousemove', (e) => {
if (isDraggingMain) {
const x = e.clientX - mainOffsetX;
const y = e.clientY - mainOffsetY;
// Confine within viewport
const maxX = window.innerWidth - mainButton.offsetWidth;
const maxY = window.innerHeight - mainButton.offsetHeight;
mainButton.style.left = Math.max(0, Math.min(x, maxX)) + 'px';
mainButton.style.bottom = Math.max(0, Math.min(window.innerHeight - y - mainButton.offsetHeight, maxY)) + 'px';
// Move additional buttons along with the main button
additionalButtons.style.left = mainButton.style.left;
additionalButtons.style.bottom = (parseInt(mainButton.style.bottom) + mainButton.offsetHeight + 10) + 'px';
}
});
document.addEventListener('mouseup', () => {
isDraggingMain = false;
});
// Screenshot functionality
function takeScreenshot() {
html2canvas(document.body).then(canvas => {
const link = document.createElement('a');
link.download = 'screenshot.png';
link.href = canvas.toDataURL();
link.click();
// Provide user feedback
alerat('Screenshot saved!');
});
}
// GroupTube functionality
let groupTubeWindow = null;
let isDragging = false;
function toggleGroupTube() {
if (groupTubeWindow) {
groupTubeWindow.style.display = groupTubeWindow.style.display === 'none' ? 'block' : 'none';
// Provide user feedback
const status = groupTubeWindow.style.display === 'none' ? 'hidden' : 'visible';
const feedbackButton = Array.from(additionalButtons.children).find(button => button.title === 'Toggle GroupTube');
if (feedbackButton) {
feedbackButton.title = `GroupTube is now ${status}`;
}
return;
}
groupTubeWindow = document.createElement('div');
groupTubeWindow.style.position = 'fixed';
groupTubeWindow.style.top = '10%';
groupTubeWindow.style.left = '10%';
groupTubeWindow.style.width = '80%';
groupTubeWindow.style.height = '80%';
groupTubeWindow.style.backgroundColor = '#222';
groupTubeWindow.style.border = '2px solid rgb(0 0 0 / 20%)';
groupTubeWindow.style.borderRadius = '10px';
groupTubeWindow.style.zIndex = '10002';
groupTubeWindow.style.overflow = 'hidden';
groupTubeWindow.style.pointerEvents = 'auto';
const iframe = document.createElement('iframe');
iframe.src = 'https://group.tube/group/70d02ed5-df92-424b-bdcd-d0c60f8ad574?join';
iframe.style.width = '100%';
iframe.style.height = 'calc(100% - 30px)';
iframe.style.border = 'none';
iframe.style.pointerEvents = 'auto';
groupTubeWindow.appendChild(iframe);
const closeButton = document.createElement('button');
closeButton.innerText = 'X';
closeButton.style.position = 'absolute';
closeButton.style.top = '1px';
closeButton.style.right = '1px';
closeButton.style.backgroundColor = 'rgb(0 0 0 / 20%)';
closeButton.style.border = 'none';
closeButton.style.color = '#fff';
closeButton.style.fontSize = '1px';
closeButton.style.cursor = 'pointer';
closeButton.style.padding = '1px 1px';
closeButton.style.borderRadius = '1px';
closeButton.onclick = () => groupTubeWindow.style.display = 'none';
groupTubeWindow.appendChild(closeButton);
container.appendChild(groupTubeWindow);
// Add drag functionality to GroupTube window
const dragHandle = document.createElement('div');
dragHandle.style.position = 'absolute';
dragHandle.style.top = '0';
dragHandle.style.left = '0';
dragHandle.style.width = '100%';
dragHandle.style.height = '12px';
dragHandle.style.cursor = 'move';
groupTubeWindow.appendChild(dragHandle);
dragHandle.addEventListener('mousedown', initDrag, false);
window.addEventListener('mousemove', doDrag, false);
window.addEventListener('mouseup', stopDrag, false);
let startX, startY;
function initDrag(e) {
startX = e.clientX - groupTubeWindow.offsetLeft;
startY = e.clientY - groupTubeWindow.offsetTop;
isDragging = true;
}
function doDrag(e) {
if (isDragging) {
groupTubeWindow.style.left = (e.clientX - startX) + 'px';
groupTubeWindow.style.top = (e.clientY - startY) + 'px';
}
}
function stopDrag() {
isDragging = false;
}
}
function resizeGroupTube(factor) {
if (groupTubeWindow) {
const currentWidth = groupTubeWindow.offsetWidth;
const currentHeight = groupTubeWindow.offsetHeight;
groupTubeWindow.style.width = (currentWidth * factor) + 'px';
groupTubeWindow.style.height = (currentHeight * factor) + 'px';
}
}
function reloadGroupTube() {
if (groupTubeWindow) {
const iframe = groupTubeWindow.querySelector('iframe');
if (iframe) {
iframe.src = iframe.src;
}
}
}
// Command functionality
const commands = {
'Owner Commands': [
"!raid tc link",
"!camsweep 5 - 30",
"!closeall",
"!kickall",
"!version",
"!whoisbot",
"!bot",
"!autokick (be careful!)",
"!autoban (be careful!)"
],
'Main Toggles': [
"!greenroomtoggle",
"!publiccommandtoggle",
"!bottoggle",
"!votetoggle",
"!greetmodetoggle",
"!imgurtoggle",
"!raidtoggle",
"!avatartoggle",
"!notificationtoggle",
"!popuptoggle",
"!soundmetertoggle",
"!timestamptoggle",
"!remindertoggle"
],
'User Management': [
"!autokick (be careful!)",
"!autoban (be careful!)",
"!userban user",
"!nickban nick",
"!userkick user",
"!nickkick nick",
"!userclose user",
"!nickclose nick"
],
'Green Room': [
"!greenroomlist",
"!greenroomlistclear",
"!greenroomadd user",
"!greenroomremove #",
"!greenroomignorelist",
"!greenroomignorelistclear",
"!greenroomignoreadd user",
"!greenroomignoreremove #"
],
'YouTube Controls': [
"!ytapi apikey",
"!ytbypass link (no playlists)",
"!yt link | keyword",
"!ytskip",
"!ytclear",
"!ytlink",
"!ytkeyword",
"!ytqueue"
],
'Ban Management': [
"!userbanlist",
"!userbanlistclear",
"!userbanadd user",
"!userbanremove #",
"!nickbanlist",
"!nickbanlistclear",
"!nickbanadd nick",
"!nickbanremove #",
"!bankeywordlist",
"!bankeywordlistclear",
"!bankeywordadd keyword | phrase",
"!bankeywordremove #"
],
'Kick Management': [
"!userkicklist",
"!userkicklistclear",
"!userkickadd user",
"!userkickremove #",
"!nickkicklist",
"!nickkicklistclear",
"!nickkickadd nick",
"!nickkickremove #",
"!kickkeywordlist",
"!kickkeywordlistclear",
"!kickkeywordadd keyword | phrase",
"!kickkeywordremove #"
],
'Operator Management': [
"!oplist",
"!oplistclear",
"!opadd user | -all",
"!opremove #",
"!optoggle"
],
'Moderator Management': [
"!modlist",
"!modlistclear",
"!modadd user",
"!modremove #"
],
'Jr. Moderator Commands': [
"!userban user",
"!nickban nick",
"!userkick user",
"!nickkick nick",
"!userclose user",
"!nickclose nick"
],
'List Management': [
"!lists",
"!listsclear",
"!userlist",
"!mentionlist",
"!mentionlistclear",
"!mentionadd keyword",
"!mentionremove #",
"!ignorelist",
"!ignorelistclear",
"!ignoreadd user",
"!ignoreremove #",
"!hiddencameralist",
"!hiddencameralistclear",
"!hiddencameraadd user",
"!hiddencameraremove #",
"!greetlist",
"!greetlistclear",
"!greetadd user | -all",
"!greetremove #",
"!ttslist",
"!ttslistclear",
"!ttsadd user | -all | -event",
"!ttsremove #",
"!highlightlist",
"!highlightlistclear",
"!highlightadd user",
"!highlightremove #",
"!reminderlist",
"!reminderlistclear",
"!reminderadd user",
"!reminderremove #",
"!safelist",
"!safelistclear",
"!safeadd user",
"!saferemove #"
],
'Settings and Utilities': [
"!fps 1 - 60",
"!clr",
"!clrall",
"!settings",
"!share"
],
'Fun Commands': [
"!coin",
"!advice",
"!8ball question",
"!roll #",
"!chuck",
"!dad",
"!vote user"
],
'Trivia Game': [
"!gameview",
"!trivia",
"!triviahelp",
"!triviahost",
"!triviaskip",
"!triviaend",
"!triviascore",
"!triviaplayerlist",
"!triviaplayerlistclear",
"!triviaadd question answer",
"!triviaremove #",
"!triviaplayeradd player",
"!triviaplayerremove player"
],
'Fish Game': [
"!gameview",
"!fish",
"!fishhelp",
"!fishhost",
"!fishupgrade",
"!fishstop",
"!fishstats",
"!fishinventory",
"!fishequip bait | rod",
"!fishevent",
"!fishleaderboard"
]
};
let commandWindow = null;
function showCommands() {
if (commandWindow) {
commandWindow.style.display = commandWindow.style.display === 'none' ? 'block' : 'none';
return;
}
commandWindow = document.createElement('div');
commandWindow.style.position = 'fixed';
commandWindow.style.top = '50%';
commandWindow.style.left = '50%';
commandWindow.style.transform = 'translate(-50%, -50%)';
commandWindow.style.width = '90%';
commandWindow.style.height = '80%';
commandWindow.style.maxWidth = '800px';
commandWindow.style.maxHeight = '600px';
commandWindow.style.overflowY = 'auto';
commandWindow.style.backgroundColor = 'rgba(34, 34, 34, 0.9)';
commandWindow.style.color = '#fff';
commandWindow.style.padding = '20px';
commandWindow.style.borderRadius = '10px';
commandWindow.style.zIndex = '10002';
commandWindow.style.boxShadow = '0 0 10px rgba(0,0,0,0.5)';
commandWindow.style.pointerEvents = 'auto';
// Add custom scrollbar styles
commandWindow.style.scrollbarWidth = 'thin';
commandWindow.style.scrollbarColor = 'rgba(85, 85, 85, 0.5) rgba(34, 34, 34, 0.3)';
// For Webkit browsers (Chrome, Safari)
const styleElement = document.createElement('style');
styleElement.textContent = `
#commandWindow::-webkit-scrollbar {
width: 8px;
}
#commandWindow::-webkit-scrollbar-track {
background: rgba(34, 34, 34, 0.3);
}
#commandWindow::-webkit-scrollbar-thumb {
background-color: rgba(85, 85, 85, 0.5);
border-radius: 4px;
}
`;
document.head.appendChild(styleElement);
commandWindow.id = 'commandWindow';
const closeButton = document.createElement('button');
closeButton.innerText = 'X';
closeButton.style.position = 'absolute';
closeButton.style.top = '10px';
closeButton.style.right = '10px';
closeButton.style.backgroundColor = 'transparent';
closeButton.style.border = 'none';
closeButton.style.color = '#fff';
closeButton.style.fontSize = '20px';
closeButton.style.cursor = 'pointer';
closeButton.onclick = () => commandWindow.style.display = 'none';
commandWindow.appendChild(closeButton);
for (const [category, categoryCommands] of Object.entries(commands)) {
const categoryTitle = document.createElement('h3');
categoryTitle.innerText = category;
categoryTitle.style.marginTop = '20px';
categoryTitle.style.marginBottom = '10px';
categoryTitle.style.fontSize = '18px';
categoryTitle.style.color = '#007bff';
commandWindow.appendChild(categoryTitle);
categoryCommands.forEach(command => {
const commandButton = document.createElement('button');
commandButton.innerText = command;
commandButton.style.display = 'block';
commandButton.style.width = '100%';
commandButton.style.padding = '10px';
commandButton.style.marginBottom = '5px';
commandButton.style.backgroundColor = 'rgba(68, 68, 68, 0.8)';
commandButton.style.border = 'none';
commandButton.style.color = '#fff';
commandButton.style.textAlign = 'left';
commandButton.style.cursor = 'pointer';
commandButton.style.borderRadius = '5px';
commandButton.style.transition = 'all 0.3s';
commandButton.style.fontSize = '14px';
commandButton.addEventListener('mouseover', () => {
commandButton.style.backgroundColor = 'rgba(85, 85, 85, 0.8)';
});
commandButton.addEventListener('mouseout', () => {
commandButton.style.backgroundColor = 'rgba(68, 68, 68, 0.8)';
});
commandButton.onclick = () => {
GM_setClipboard(command);
commandButton.style.backgroundColor = 'rgba(0, 123, 255, 0.8)';
commandButton.innerText = 'Copied!';
setTimeout(() => {
commandButton.style.backgroundColor = 'rgba(68, 68, 68, 0.8)';
commandButton.innerText = command;
}, 1000);
};
commandWindow.appendChild(commandButton);
});
}
container.appendChild(commandWindow);
// Make command window draggable
let isDraggingCmd = false;
let cmdStartX, cmdStartY;
const cmdDragHandle = document.createElement('div');
cmdDragHandle.style.position = 'absolute';
cmdDragHandle.style.top = '0';
cmdDragHandle.style.left = '0';
cmdDragHandle.style.width = '100%';
cmdDragHandle.style.height = '30px';
cmdDragHandle.style.cursor = 'move';
cmdDragHandle.style.backgroundColor = 'rgb(0 0 0 / 20%)';
commandWindow.insertBefore(cmdDragHandle, commandWindow.firstChild);
cmdDragHandle.addEventListener('mousedown', initCmdDrag, false);
window.addEventListener('mousemove', doCmdDrag, false);
window.addEventListener('mouseup', stopCmdDrag, false);
function initCmdDrag(e) {
isDraggingCmd = true;
cmdStartX = e.clientX - commandWindow.offsetLeft;
cmdStartY = e.clientY - commandWindow.offsetTop;
}
function doCmdDrag(e) {
if (!isDraggingCmd) return;
let newX = e.clientX - cmdStartX;
let newY = e.clientY - cmdStartY;
// Confine the window within the viewport
const rect = commandWindow.getBoundingClientRect();
newX = Math.max(0, Math.min(newX, window.innerWidth - rect.width));
newY = Math.max(0, Math.min(newY, window.innerHeight - rect.height));
commandWindow.style.left = newX + 'px';
commandWindow.style.top = newY + 'px';
commandWindow.style.transform = 'none';
}
function stopCmdDrag() {
isDraggingCmd = false;
}
}
// Ensure the window stays within bounds when the browser is resized
window.addEventListener('resize', adjustCommandWindowPosition);
function adjustCommandWindowPosition() {
if (commandWindow) {
const rect = commandWindow.getBoundingClientRect();
let newX = rect.left;
let newY = rect.top;
if (rect.right > window.innerWidth) {
newX = window.innerWidth - rect.width;
}
if (rect.bottom > window.innerHeight) {
newY = window.innerHeight - rect.height;
}
newX = Math.max(0, newX);
newY = Math.max(0, newY);
commandWindow.style.left = newX + 'px';
commandWindow.style.top = newY + 'px';
}
}
})();