- // ==UserScript==
- // @name Drawaria Moderator Menu With Tools
- // @namespace drawaria.moderator.tool
- // @version 3.0
- // @description Enhanced real-time moderator tool for Drawaria with additional features, custom chat messages, and improved visuals
- // @author YouTube And Minish
- // @match https://drawaria.online/*
- // @grant none
- // @license MIT
- // ==/UserScript==
-
- (function() {
- 'use strict';
-
- // Initialize data structures
- const bannedPlayers = new Set();
- const mutedPlayers = new Set();
- const reportedPlayers = [];
- const warnedPlayers = new Map();
- const suspiciousPlayers = new Set();
-
- // Style definitions
- const styles = `
- #moderatorMenuContainer {
- position: fixed;
- bottom: 60px;
- right: 10px;
- z-index: 1000;
- background-color: #333;
- border-radius: 5px;
- padding: 0;
- color: white;
- width: 250px;
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
- cursor: move;
- font-family: Arial, sans-serif;
- }
- #moderatorMenuTitle {
- padding: 10px;
- background-color: #555;
- border-radius: 5px 5px 0 0;
- text-align: center;
- cursor: pointer;
- display: flex;
- justify-content: space-between;
- align-items: center;
- }
- #moderatorMenuContent {
- padding: 10px;
- display: none;
- }
- .menuButton {
- display: block;
- width: 100%;
- margin-bottom: 5px;
- padding: 10px;
- background-color: #444;
- color: white;
- border: none;
- border-radius: 5px;
- cursor: pointer;
- transition: background-color 0.3s;
- text-align: left;
- }
- .menuButton:hover {
- background-color: #666;
- }
- .menuButton i {
- margin-right: 10px;
- }
- .playerList {
- max-height: 200px;
- overflow-y: auto;
- border: 1px solid #555;
- border-radius: 5px;
- margin-top: 10px;
- }
- .playerListItem {
- padding: 5px;
- border-bottom: 1px solid #555;
- }
- .highlight {
- background-color: #ff9999;
- }
- `;
-
- // Create the moderator menu
- function createModeratorMenu() {
- const menuContainer = document.createElement('div');
- menuContainer.id = 'moderatorMenuContainer';
- document.body.appendChild(menuContainer);
-
- const styleElement = document.createElement('style');
- styleElement.textContent = styles;
- document.head.appendChild(styleElement);
-
- const menuTitle = document.createElement('div');
- menuTitle.id = 'moderatorMenuTitle';
- menuTitle.innerHTML = '<span>Moderator Menu</span><span id="toggleArrow">▼</span>';
- menuContainer.appendChild(menuTitle);
-
- const menuContent = document.createElement('div');
- menuContent.id = 'moderatorMenuContent';
- menuContainer.appendChild(menuContent);
-
- menuTitle.addEventListener('click', () => {
- menuContent.style.display = menuContent.style.display === 'none' ? 'block' : 'none';
- const toggleArrow = document.getElementById('toggleArrow');
- toggleArrow.innerText = menuContent.style.display === 'none' ? '▼' : '▲';
- });
-
- // Add buttons to the menu
- addMenuButton(menuContent, '<i class="fas fa-ban"></i> Ban Player', handleBanButtonClick);
- addMenuButton(menuContent, '<i class="fas fa-undo"></i> Unban Player', handleUnbanButtonClick);
- addMenuButton(menuContent, '<i class="fas fa-volume-mute"></i> Mute Player', handleMuteButtonClick);
- addMenuButton(menuContent, '<i class="fas fa-volume-up"></i> Unmute Player', handleUnmuteButtonClick);
- addMenuButton(menuContent, '<i class="fas fa-exclamation-triangle"></i> Warn Player', handleWarnButtonClick);
- addMenuButton(menuContent, '<i class="fas fa-flag"></i> Report Player', handleReportButtonClick);
- addMenuButton(menuContent, '<i class="fas fa-eye"></i> View Reports', handleViewReportsClick);
- addMenuButton(menuContent, '<i class="fas fa-users"></i> View Banned Players', handleViewBannedPlayersClick);
- addMenuButton(menuContent, '<i class="fas fa-microphone-alt-slash"></i> View Muted Players', handleViewMutedPlayersClick);
- addMenuButton(menuContent, '<i class="fas fa-user-times"></i> Kick Player', handleKickButtonClick);
- addMenuButton(menuContent, '<i class="fas fa-exclamation"></i> Highlight Suspicious', handleHighlightSuspiciousClick);
-
- // Create player lists
- createPlayerList(menuContent, 'bannedPlayersList', 'Banned Players');
- createPlayerList(menuContent, 'mutedPlayersList', 'Muted Players');
- createPlayerList(menuContent, 'warnedPlayersList', 'Warned Players');
- createPlayerList(menuContent, 'reportedPlayersList', 'Reported Players');
- createPlayerList(menuContent, 'suspiciousPlayersList', 'Suspicious Players');
-
- // Make the menu draggable
- makeDraggable(menuContainer);
- }
-
- // Add a button to the menu
- function addMenuButton(menu, text, onClick) {
- const button = document.createElement('button');
- button.innerHTML = text;
- button.className = 'menuButton';
- button.addEventListener('click', onClick);
- menu.appendChild(button);
- }
-
- // Create a player list
- function createPlayerList(menu, id, title) {
- const listTitle = document.createElement('h3');
- listTitle.textContent = title;
- menu.appendChild(listTitle);
-
- const listContainer = document.createElement('div');
- listContainer.id = id;
- listContainer.className = 'playerList';
- menu.appendChild(listContainer);
- }
-
- // Function to handle the "Ban" button click event
- function handleBanButtonClick() {
- const nickname = prompt("Enter the player's nickname to ban:");
-
- if (nickname) {
- bannedPlayers.add(nickname);
- addModeratorMessages(nickname, 'Ban');
- removePlayer(nickname);
- updatePlayerList();
- disableChatWithUser(nickname);
- broadcastBanMessage(nickname);
- updateBannedPlayersList();
- }
- }
-
- // Function to handle the "Unban" button click event
- function handleUnbanButtonClick() {
- const nickname = prompt("Enter the player's nickname to unban:");
-
- if (nickname) {
- if (bannedPlayers.has(nickname)) {
- bannedPlayers.delete(nickname);
- addModeratorMessages(nickname, 'Unban');
- updatePlayerList();
- enableChatWithUser(nickname);
- broadcastUnbanMessage(nickname);
- updateBannedPlayersList();
- } else {
- alert('Player is not banned.');
- }
- }
- }
-
- // Function to handle the "Mute" button click event
- function handleMuteButtonClick() {
- const nickname = prompt("Enter the player's nickname to mute:");
-
- if (nickname) {
- mutedPlayers.add(nickname);
- addModeratorMessages(nickname, 'Mute');
- disableChatWithUser(nickname);
- updateMutedPlayersList();
- }
- }
-
- // Function to handle the "Unmute" button click event
- function handleUnmuteButtonClick() {
- const nickname = prompt("Enter the player's nickname to unmute:");
-
- if (nickname) {
- if (mutedPlayers.has(nickname)) {
- mutedPlayers.delete(nickname);
- addModeratorMessages(nickname, 'Unmute');
- enableChatWithUser(nickname);
- updateMutedPlayersList();
- } else {
- alert('Player is not muted.');
- }
- }
- }
-
- // Function to handle the "Warn" button click event
- function handleWarnButtonClick() {
- const nickname = prompt("Enter the player's nickname to warn:");
- const reason = prompt("Enter the reason for the warning:");
-
- if (nickname && reason) {
- if (warnedPlayers.has(nickname)) {
- warnedPlayers.set(nickname, warnedPlayers.get(nickname) + 1);
- } else {
- warnedPlayers.set(nickname, 1);
- }
- addModeratorMessages(nickname, 'Warn', reason);
- updateWarnedPlayersList();
- if (warnedPlayers.get(nickname) >= 3) {
- if (confirm(`Player ${nickname} has 3 warnings. Do you want to ban them?`)) {
- handleBanButtonClick(nickname);
- }
- }
- }
- }
-
- // Function to handle the "Report" button click event
- function handleReportButtonClick() {
- const nickname = prompt("Enter the player's nickname to report:");
- const reason = prompt("Enter the reason for the report:");
-
- if (nickname && reason) {
- reportedPlayers.push({ nickname, reason, timestamp: new Date() });
- addModeratorMessages(nickname, 'Report', reason);
- updateReportedPlayersList();
- }
- }
-
- // Function to handle the "View Reports" button click event
- function handleViewReportsClick() {
- const sortedReports = reportedPlayers.sort((a, b) => b.timestamp - a.timestamp);
- const reports = sortedReports.map(player => `${player.nickname}: ${player.reason} (at ${player.timestamp.toLocaleString()})`).join('\n');
- alert(reports || 'No reports available.');
- }
-
- // Function to handle the "View Banned Players" button click event
- function handleViewBannedPlayersClick() {
- const banned = Array.from(bannedPlayers).join('\n');
- alert(banned || 'No banned players.');
- }
-
- // Function to handle the "View Muted Players" button click event
- function handleViewMutedPlayersClick() {
- const muted = Array.from(mutedPlayers).join('\n');
- alert(muted || 'No muted players.');
- }
-
- // Function to handle the "Kick" button click event
- function handleKickButtonClick() {
- const nickname = prompt("Enter the player's nickname to kick:");
-
- if (nickname) {
- addModeratorMessages(nickname, 'Kick');
- removePlayer(nickname);
- updatePlayerList();
- broadcastKickMessage(nickname);
- }
- }
-
- // Function to handle the "Highlight Suspicious" button click event
- function handleHighlightSuspiciousClick() {
- const nickname = prompt("Enter the player's nickname to highlight as suspicious:");
-
- if (nickname) {
- suspiciousPlayers.add(nickname);
- highlightPlayer(nickname);
- updateSuspiciousPlayersList();
- }
- }
-
- // Function to add moderator messages with custom formatting
- function addModeratorMessages(nickname, action, additionalInfo = '') {
- const chatBox = document.getElementById('chatbox_messages');
-
- if (chatBox) {
- let messages = [];
-
- if (action === 'Ban') {
- messages = [
- `<div class="chatmessage systemchatmessage5" data-ts="${Date.now()}">Moderator: Banned ${nickname}</div>`,
- `<div class="chatmessage systemchatmessage7" data-ts="${Date.now()}">Complain about the moderator on Discord, on this channel: <a href="https://discord.gg/XeVKWWs" target="_blank">#report-a-moderator</a></div>`,
- `<div class="chatmessage systemchatmessage" data-ts="${Date.now()}">Someone voted to ban from the room: ${nickname}</div>`,
- `<div class="chatmessage systemchatmessage" data-ts="${Date.now()}">${nickname} has been banned from the room!</div>`,
- `<div class="chatmessage systemchatmessage7" data-ts="${Date.now()}">${nickname} - player has left the room</div>`
- ];
- } else if (action === 'Unban') {
- messages = [
- `<div class="chatmessage systemchatmessage5" data-ts="${Date.now()}">Moderator: Unbanned ${nickname}</div>`,
- `<div class="chatmessage systemchatmessage" data-ts="${Date.now()}">${nickname} has been unbanned from the room!</div>`
- ];
- } else if (action === 'Mute') {
- messages = [
- `<div class="chatmessage systemchatmessage5" data-ts="${Date.now()}">Moderator: Muted ${nickname}</div>`,
- `<div class="chatmessage systemchatmessage" data-ts="${Date.now()}">${nickname} has been muted in the room!</div>`
- ];
- } else if (action === 'Unmute') {
- messages = [
- `<div class="chatmessage systemchatmessage5" data-ts="${Date.now()}">Moderator: Unmuted ${nickname}</div>`,
- `<div class="chatmessage systemchatmessage" data-ts="${Date.now()}">${nickname} has been unmuted in the room!</div>`
- ];
- } else if (action === 'Warn') {
- messages = [
- `<div class="chatmessage systemchatmessage5" data-ts="${Date.now()}">Moderator: Warned ${nickname} for: ${additionalInfo}</div>`,
- `<div class="chatmessage systemchatmessage" data-ts="${Date.now()}">${nickname} has been warned! (${warnedPlayers.get(nickname)}/3)</div>`
- ];
- } else if (action === 'Report') {
- messages = [
- `<div class="chatmessage systemchatmessage5" data-ts="${Date.now()}">Moderator: Reported ${nickname}</div>`,
- `<div class="chatmessage systemchatmessage" data-ts="${Date.now()}">${nickname} has been reported for: ${additionalInfo}</div>`
- ];
- } else if (action === 'Kick') {
- messages = [
- `<div class="chatmessage systemchatmessage5" data-ts="${Date.now()}">Moderator: Kicked ${nickname}</div>`,
- `<div class="chatmessage systemchatmessage" data-ts="${Date.now()}">${nickname} has been kicked from the room!</div>`
- ];
- }
-
- messages.forEach(message => {
- chatBox.innerHTML += message;
- });
- }
- }
-
- // Function to remove a player from the list
- function removePlayer(nickname) {
- const playerList = document.getElementById('playerlist');
-
- if (playerList) {
- const playerToRemove = Array.from(playerList.querySelectorAll('.playerlist-row')).find(player => {
- const nameElement = player.querySelector('.playerlist-name a');
- return nameElement && nameElement.textContent.trim() === nickname;
- });
-
- if (playerToRemove) {
- playerToRemove.remove();
- }
- }
- }
-
- // Function to update the player list
- function updatePlayerList() {
- const playerList = document.getElementById('playerlist');
-
- if (playerList) {
- Array.from(playerList.querySelectorAll('.playerlist-row')).forEach(player => {
- const nameElement = player.querySelector('.playerlist-name a');
- if (nameElement) {
- const playerName = nameElement.textContent.trim();
- if (bannedPlayers.has(playerName)) {
- player.remove();
- }
- }
- });
- }
- }
-
- // Function to sanitize nickname for use in CSS selectors
- function sanitizeNickname(nickname) {
- return nickname.replace(/[^a-zA-Z0-9]/g, '');
- }
-
- // Function to disable chat with the banned player
- function disableChatWithUser(nickname) {
- const sanitizedNickname = sanitizeNickname(nickname);
- const chatWithUser = document.querySelector(`.chat-with-${sanitizedNickname}`);
-
- if (chatWithUser) {
- chatWithUser.style.display = 'none';
- }
- }
-
- // Function to enable chat with the unbanned player
- function enableChatWithUser(nickname) {
- const sanitizedNickname = sanitizeNickname(nickname);
- const chatWithUser = document.querySelector(`.chat-with-${sanitizedNickname}`);
-
- if (chatWithUser) {
- chatWithUser.style.display = 'block';
- }
- }
-
- // Function to broadcast the ban message to all players
- function broadcastBanMessage(nickname) {
- if (window.myRoom.players && Array.isArray(window.myRoom.players)) {
- const message = JSON.stringify([
- "bc_uc_freedrawsession_changedroom",
- null,
- null,
- window.myRoom.players.filter(player => player.nickname !== nickname)
- ]);
- sendMessageToAll(`42${message}`);
- }
- }
-
- // Function to broadcast the unban message to all players
- function broadcastUnbanMessage(nickname) {
- if (window.myRoom.players && Array.isArray(window.myRoom.players)) {
- const message = JSON.stringify([
- "bc_uc_freedrawsession_changedroom",
- null,
- null,
- window.myRoom.players
- ]);
- sendMessageToAll(`42${message}`);
- }
- }
-
- // Function to broadcast the kick message to all players
- function broadcastKickMessage(nickname) {
- if (window.myRoom.players && Array.isArray(window.myRoom.players)) {
- const message = JSON.stringify([
- "bc_uc_freedrawsession_changedroom",
- null,
- null,
- window.myRoom.players.filter(player => player.nickname !== nickname)
- ]);
- sendMessageToAll(`42${message}`);
- }
- }
-
- // Function to update the banned players list
- function updateBannedPlayersList() {
- updatePlayerListContainer('bannedPlayersList', Array.from(bannedPlayers));
- }
-
- // Function to update the muted players list
- function updateMutedPlayersList() {
- updatePlayerListContainer('mutedPlayersList', Array.from(mutedPlayers));
- }
-
- // Function to update the warned players list
- function updateWarnedPlayersList() {
- const warnedList = Array.from(warnedPlayers).map(([name, count]) => `${name} (${count}/3)`);
- updatePlayerListContainer('warnedPlayersList', warnedList);
- }
-
- // Function to update the reported players list
- function updateReportedPlayersList() {
- const reportedList = reportedPlayers.map(player => `${player.nickname}: ${player.reason}`);
- updatePlayerListContainer('reportedPlayersList', reportedList);
- }
-
- // Function to update the suspicious players list
- function updateSuspiciousPlayersList() {
- updatePlayerListContainer('suspiciousPlayersList', Array.from(suspiciousPlayers));
- }
-
- // Generic function to update player list containers
- function updatePlayerListContainer(containerId, playerList) {
- const listContainer = document.getElementById(containerId);
- if (listContainer) {
- listContainer.innerHTML = '';
- playerList.forEach(player => {
- const playerItem = document.createElement('div');
- playerItem.textContent = player;
- playerItem.className = 'playerListItem';
- listContainer.appendChild(playerItem);
- });
- }
- }
-
- // Function to highlight a suspicious player
- function highlightPlayer(nickname) {
- const playerList = document.getElementById('playerlist');
- if (playerList) {
- const playerToHighlight = Array.from(playerList.querySelectorAll('.playerlist-row')).find(player => {
- const nameElement = player.querySelector('.playerlist-name a');
- return nameElement && nameElement.textContent.trim() === nickname;
- });
-
- if (playerToHighlight) {
- playerToHighlight.classList.add('highlight');
- }
- }
- }
-
- // WebSocket handling
- const originalSend = WebSocket.prototype.send;
- WebSocket.prototype.send = function (...args) {
- if (window.sockets.indexOf(this) === -1) {
- window.sockets.push(this);
-
- if (window.sockets.indexOf(this) === 0) {
- this.addEventListener('message', handleIncomingMessage);
- }
- }
-
- return originalSend.call(this, ...args);
- };
-
- // Initialize
- createModeratorMenu();
-
- // Room & Socket Control
- window.myRoom = {
- players: []
- };
- window.sockets = [];
-
- // Ensure the WebSocket messages are correctly formatted and sent to all players
- function sendMessageToAll(message) {
- window.sockets.forEach(socket => {
- if (socket.readyState === WebSocket.OPEN) {
- socket.send(message);
- }
- });
- }
-
- // Function to handle incoming WebSocket messages
- function handleIncomingMessage(event) {
- let message = String(event.data);
-
- if (message.startsWith('42')) {
- let payload = JSON.parse(message.slice(2));
-
- if (payload[0] == 'bc_uc_freedrawsession_changedroom' || payload[0] == 'mc_roomplayerschange') {
- window.myRoom.players = payload[3];
- updatePlayerList();
- updateBannedPlayersList();
- updateMutedPlayersList();
- updateWarnedPlayersList();
- updateReportedPlayersList();
- updateSuspiciousPlayersList();
- }
- } else if (message.startsWith('430')) {
- let configs = JSON.parse(message.slice(3))[0];
- window.myRoom.players = configs.players;
- window.myRoom.id = configs.roomid;
- updatePlayerList();
- updateBannedPlayersList();
- updateMutedPlayersList();
- updateWarnedPlayersList();
- updateReportedPlayersList();
- updateSuspiciousPlayersList();
- }
- }
-
- // Connect to the WebSocket server
- function connectToWebSocketServer() {
- const socket = new WebSocket('wss://sv3.drawaria.online/socket.io/?sid1=s%3A11JLEUID6B8TEN3-RCEDSV1h8ZzvoF3a.99s79DOPC%2Fb2ajOJBEBNkhMT0Z1FSm8jzcCGzohk%2FeI&hostname=drawaria.online&EIO=3&transport=websocket');
-
- socket.onopen = () => {
- console.log('WebSocket connection opened');
- window.sockets.push(socket);
- socket.addEventListener('message', handleIncomingMessage);
- };
-
- socket.onclose = () => {
- console.log('WebSocket connection closed');
- window.sockets = window.sockets.filter(s => s !== socket);
- };
-
- socket.onerror = (error) => {
- console.error('WebSocket error:', error);
- };
- }
-
- // Connect to the WebSocket server
- connectToWebSocketServer();
-
- // Make an element draggable
- function makeDraggable(element) {
- let isDragging = false;
- let offsetX, offsetY;
-
- element.addEventListener('mousedown', (e) => {
- isDragging = true;
- offsetX = e.clientX - element.getBoundingClientRect().left;
- offsetY = e.clientY - element.getBoundingClientRect().top;
- element.style.cursor = 'grabbing';
- });
-
- document.addEventListener('mousemove', (e) => {
- if (isDragging) {
- element.style.left = `${e.clientX - offsetX}px`;
- element.style.top = `${e.clientY - offsetY}px`;
- element.style.bottom = 'auto';
- element.style.right = 'auto';
- }
- });
-
- document.addEventListener('mouseup', () => {
- isDragging = false;
- element.style.cursor = 'move';
- });
- }
-
- // Add custom chat commands for moderators
- function addCustomChatCommands() {
- const originalSendChat = window.sendChat;
- window.sendChat = function(message) {
- if (message.startsWith('/')) {
- const [command, ...args] = message.slice(1).split(' ');
- handleChatCommand(command, args);
- } else {
- originalSendChat.call(this, message);
- }
- };
- }
-
- // Handle custom chat commands
- function handleChatCommand(command, args) {
- switch(command.toLowerCase()) {
- case 'ban':
- if (args.length > 0) {
- handleBanButtonClick(args.join(' '));
- }
- break;
- case 'unban':
- if (args.length > 0) {
- handleUnbanButtonClick(args.join(' '));
- }
- break;
- case 'mute':
- if (args.length > 0) {
- handleMuteButtonClick(args.join(' '));
- }
- break;
- case 'unmute':
- if (args.length > 0) {
- handleUnmuteButtonClick(args.join(' '));
- }
- break;
- case 'kick':
- if (args.length > 0) {
- handleKickButtonClick(args.join(' '));
- }
- break;
- case 'warn':
- if (args.length > 1) {
- handleWarnButtonClick(args[0], args.slice(1).join(' '));
- }
- break;
- case 'report':
- if (args.length > 1) {
- handleReportButtonClick(args[0], args.slice(1).join(' '));
- }
- break;
- case 'highlight':
- if (args.length > 0) {
- handleHighlightSuspiciousClick(args.join(' '));
- }
- break;
- default:
- addModeratorMessages('System', 'Unknown command', `Unknown command: /${command}`);
- }
- }
-
- // Initialize custom chat commands
- addCustomChatCommands();
-
- })();