您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Search for player names and display a warning message if found.
// ==UserScript== // @name Blacklist & Warning for AutoDarts // @namespace Owl // @version 0.1 // @description Search for player names and display a warning message if found. // @match https://play.autodarts.io/* // @run-at document-idle // @license MIT // @grant none // ==/UserScript== (function() { 'use strict'; console.log("[Blacklist Script] Starting (EN) - File Import/Export..."); let blacklistedPlayers = JSON.parse(localStorage.getItem('blacklistedPlayers')) || []; function savePlayerList() { localStorage.setItem('blacklistedPlayers', JSON.stringify(blacklistedPlayers)); } // Popup variables let popupVisible = false; let popupContainer = null; // Menu item ID const MENU_ITEM_ID = 'autodarts-blacklist-menu-item'; // -------------------------------------------------- // A) DRAG LOGIC // -------------------------------------------------- let isDragging = false; let offsetX = 0; let offsetY = 0; let hasConvertedCenter = false; function onDragMouseDown(e) { e.preventDefault(); if (!hasConvertedCenter) { convertCenterToAbsolutePosition(popupContainer); hasConvertedCenter = true; } isDragging = true; offsetX = popupContainer.offsetLeft - e.clientX; offsetY = popupContainer.offsetTop - e.clientY; } function onDragMouseMove(e) { if (!isDragging) return; e.preventDefault(); const newLeft = e.clientX + offsetX; const newTop = e.clientY + offsetY; popupContainer.style.left = newLeft + 'px'; popupContainer.style.top = newTop + 'px'; } function onDragMouseUp() { isDragging = false; } function convertCenterToAbsolutePosition(elem) { const rect = elem.getBoundingClientRect(); elem.style.left = rect.left + 'px'; elem.style.top = rect.top + 'px'; elem.style.transform = 'none'; } // -------------------------------------------------- // B) CREATE POPUP // -------------------------------------------------- function createPopup() { if (popupContainer) return; popupContainer = document.createElement('div'); popupContainer.id = 'autodarts-blacklist-popup'; Object.assign(popupContainer.style, { position: 'fixed', left: '50%', top: '50%', transform: 'translate(-50%, -50%)', padding: '20px', backgroundColor: '#1A202C', // dark gray color: '#E2E8F0', border: '1px solid #2D3748', borderRadius: '8px', boxShadow: '0 0 10px rgba(0,0,0,0.5)', zIndex: '99999', fontFamily: 'sans-serif', width: 'auto', minWidth: '300px', maxWidth: '80vw', maxHeight: '80vh', overflowY: 'auto', display: 'none' }); // Drag bar const dragBar = document.createElement('div'); dragBar.style.height = '20px'; dragBar.style.cursor = 'move'; dragBar.style.marginBottom = '10px'; popupContainer.appendChild(dragBar); // Close "X" button const closeXButton = document.createElement('button'); closeXButton.textContent = '×'; Object.assign(closeXButton.style, { position: 'absolute', top: '4px', right: '8px', background: 'transparent', border: 'none', color: '#E2E8F0', fontSize: '20px', lineHeight: '20px', cursor: 'pointer' }); closeXButton.addEventListener('click', () => { togglePopup(false); }); popupContainer.appendChild(closeXButton); // Title const title = document.createElement('h2'); title.textContent = 'BLACKLIST'; title.style.marginTop = '0'; title.style.fontSize = '1.4rem'; title.style.fontWeight = 'bold'; popupContainer.appendChild(title); // Input area const inputWrapper = document.createElement('div'); inputWrapper.style.display = 'flex'; inputWrapper.style.marginBottom = '10px'; popupContainer.appendChild(inputWrapper); const input = document.createElement('input'); input.type = 'text'; input.placeholder = 'Enter new player name'; Object.assign(input.style, { flex: '1', marginRight: '5px', padding: '4px 8px' }); inputWrapper.appendChild(input); const addButton = document.createElement('button'); addButton.textContent = 'Add'; Object.assign(addButton.style, { padding: '4px 8px', cursor: 'pointer', backgroundColor: 'rgba(59, 182, 43, 1)', color: '#fff', border: 'none', borderRadius: '4px' }); inputWrapper.appendChild(addButton); // UL list const listElement = document.createElement('ul'); listElement.style.listStyle = 'none'; listElement.style.paddingLeft = '0'; popupContainer.appendChild(listElement); // Add function function addName() { const name = input.value.trim(); const uppercaseName = name.toUpperCase(); if (uppercaseName && !blacklistedPlayers.includes(uppercaseName)) { blacklistedPlayers.push(uppercaseName); savePlayerList(); updateList(listElement); } input.value = ''; } addButton.addEventListener('click', addName); input.addEventListener('keydown', (e) => { if (e.key === 'Enter') { e.preventDefault(); addName(); } }); // Show the list initially updateList(listElement); // IMPORT/EXPORT section const importExportWrapper = document.createElement('div'); importExportWrapper.style.borderTop = '1px solid #2D3748'; importExportWrapper.style.paddingTop = '10px'; importExportWrapper.style.marginTop = '10px'; popupContainer.appendChild(importExportWrapper); // Export button const exportButton = document.createElement('button'); exportButton.textContent = 'Export'; Object.assign(exportButton.style, { padding: '4px 8px', cursor: 'pointer', marginRight: '10px', backgroundColor: '#2D3748', color: '#fff', border: 'none', borderRadius: '4px' }); exportButton.addEventListener('click', () => { const data = JSON.stringify(blacklistedPlayers, null, 2); // 1) Copy to clipboard navigator.clipboard.writeText(data) .then(() => { alert('Blacklist has been copied to your clipboard.'); // 2) Ask if user wants to save as file const saveFile = confirm('Do you want to save it as a JSON file?'); if (saveFile) { // Create a Blob, then force a download const blob = new Blob([data], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'blacklist.json'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } }) .catch(err => { alert('Failed to copy blacklist: ' + err); }); }); importExportWrapper.appendChild(exportButton); // Import button const importButton = document.createElement('button'); importButton.textContent = 'Import'; Object.assign(importButton.style, { padding: '4px 8px', cursor: 'pointer', backgroundColor: '#2D3748', color: '#fff', border: 'none', borderRadius: '4px' }); importButton.addEventListener('click', () => { const choice = confirm('Would you like to import from file instead of JSON text?\nClick "OK" for file, "Cancel" for text prompt.'); if (choice) { // Import from file importFromFile(listElement); } else { // Use prompt importFromPrompt(listElement); } }); importExportWrapper.appendChild(importButton); document.body.appendChild(popupContainer); // Register drag events dragBar.addEventListener('mousedown', onDragMouseDown); document.addEventListener('mousemove', onDragMouseMove); document.addEventListener('mouseup', onDragMouseUp); } // ---- IMPORT FROM FILE ---- function importFromFile(listElement) { const fileInput = document.createElement('input'); fileInput.type = 'file'; fileInput.accept = 'application/json,.json'; fileInput.style.display = 'none'; fileInput.addEventListener('change', function() { if (fileInput.files && fileInput.files[0]) { const file = fileInput.files[0]; const reader = new FileReader(); reader.onload = function(e) { try { const content = e.target.result; const importedList = JSON.parse(content); if (Array.isArray(importedList)) { // Convert all to uppercase importedList.forEach((val, idx) => { importedList[idx] = val.toUpperCase(); }); blacklistedPlayers = importedList; savePlayerList(); updateList(listElement); checkPlayers(); alert('Blacklist imported successfully from file!'); } else { alert('Invalid JSON data in file: Must be an array, e.g. ["Alice","Bob"].'); } } catch (err) { alert('Invalid JSON file: ' + err); } }; reader.readAsText(file); } }); // "Click" the input programmatically document.body.appendChild(fileInput); fileInput.click(); // Remove it afterwards to keep the DOM clean fileInput.parentNode.removeChild(fileInput); } // ---- IMPORT FROM PROMPT ---- function importFromPrompt(listElement) { const inputData = prompt('Paste the JSON data for the blacklist:'); if (inputData) { try { const importedList = JSON.parse(inputData); if (Array.isArray(importedList)) { // Optional: convert all to uppercase importedList.forEach((val, idx) => { importedList[idx] = val.toUpperCase(); }); blacklistedPlayers = importedList; savePlayerList(); updateList(listElement); checkPlayers(); alert('Blacklist imported successfully!'); } else { alert('Invalid JSON data: Must be an array, e.g. ["Alice","Bob"].'); } } catch (e) { alert('Invalid JSON: ' + e); } } } function updateList(listElement) { listElement.innerHTML = ''; blacklistedPlayers.forEach(name => { const li = document.createElement('li'); li.textContent = name; Object.assign(li.style, { display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '4px 0' }); const removeBtn = document.createElement('button'); removeBtn.textContent = 'X'; Object.assign(removeBtn.style, { marginLeft: '10px', backgroundColor: '#C53030', color: '#fff', border: 'none', borderRadius: '4px', padding: '2px 8px', cursor: 'pointer' }); removeBtn.addEventListener('click', () => { blacklistedPlayers = blacklistedPlayers.filter(player => player !== name); savePlayerList(); updateList(listElement); checkPlayers(); }); li.appendChild(removeBtn); listElement.appendChild(li); }); } function togglePopup(forceOpen) { if (!popupContainer) { createPopup(); } popupVisible = (typeof forceOpen === 'boolean') ? forceOpen : !popupVisible; popupContainer.style.display = popupVisible ? 'block' : 'none'; } // -------------------------------------------------- // WARNING AT THE TOP // -------------------------------------------------- let warningDiv = null; function showWarning(text) { if (!warningDiv) { warningDiv = document.createElement('div'); Object.assign(warningDiv.style, { position: 'fixed', top: '0', left: '0', width: '100%', backgroundColor: 'red', color: 'white', padding: '10px', textAlign: 'center', zIndex: '100000', fontSize: '16px' }); document.body.appendChild(warningDiv); } warningDiv.textContent = `Attention: ${text}`; } function removeWarning() { if (warningDiv) { warningDiv.remove(); warningDiv = null; } } function checkPlayers() { const playerTags = document.querySelectorAll('p.chakra-text.css-0'); let foundNames = []; playerTags.forEach(tag => { const name = tag.textContent.trim().toUpperCase(); if (blacklistedPlayers.includes(name)) { if (tag.style.backgroundColor !== 'red' || tag.style.color !== 'white') { tag.style.backgroundColor = 'red'; tag.style.color = 'white'; } foundNames.push(name); } else { if (tag.style.backgroundColor === 'red' || tag.style.color === 'white') { tag.style.backgroundColor = ''; tag.style.color = ''; } } }); if (foundNames.length > 0) { showWarning(`Players found: ${foundNames.join(', ')}`); } else { removeWarning(); } } // -------------------------------------------------- // MENU ITEM // -------------------------------------------------- function addBlacklistMenuItem(menuContainer) { console.log("[Blacklist Script] Adding the blacklist menu item..."); let blacklistLink = document.getElementById(MENU_ITEM_ID); if (!blacklistLink) { blacklistLink = document.createElement('a'); blacklistLink.id = MENU_ITEM_ID; blacklistLink.textContent = 'Blacklist'; blacklistLink.className = 'chakra-button css-1nal3hj'; blacklistLink.style.cursor = 'pointer'; const icon = document.createElement('span'); icon.className = 'chakra-button__icon css-1wh2kri'; icon.style.marginRight = '0.5rem'; icon.innerHTML = ` <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 2C6.49 2 2 6.49 2 12s4.49 10 10 10 10-4.49 10-10S17.51 2 12 2zm3 14H9v-2h6v2zm2-4H7V8h10v4z"/> </svg>`; blacklistLink.prepend(icon); menuContainer.appendChild(blacklistLink); blacklistLink.addEventListener('click', () => { togglePopup(); }); } } // -------------------------------------------------- // MUTATIONOBSERVER MIT DEBOUNCE // -------------------------------------------------- let checkTimeout = null; function triggerCheckWithDebounce() { if (checkTimeout) { clearTimeout(checkTimeout); } checkTimeout = setTimeout(() => { checkPlayers(); checkTimeout = null; }, 300); } const observer = new MutationObserver(() => { triggerCheckWithDebounce(); }); observer.observe(document.body, { childList: true, subtree: true }); // -------------------------------------------------- // MENU FIND + ADD // -------------------------------------------------- const intervalId = setInterval(() => { const menuContainer = [...document.querySelectorAll('div.chakra-stack')] .find(div => div.querySelector('a[href="/"]') && div.querySelector('a[href="/lobbies"]')); if (menuContainer) { console.log("[Blacklist Script] Menu found:", menuContainer); addBlacklistMenuItem(menuContainer); clearInterval(intervalId); } else { console.log("[Blacklist Script] Menu not found yet. Trying again..."); } }, 1000); // Start checkPlayers(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址