您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Epic fixes and visual mods for fishtank.live
当前为
// ==UserScript== // @name Grizzway Tools // @namespace http://tampermonkey.net/ // @version 4.7.1 // @description Epic fixes and visual mods for fishtank.live // @author Grizzway // @match *://*.fishtank.live/* // @grant GM_addStyle // @license MIT // ==/UserScript== (function() { 'use strict'; // User-editable color for stream title const streamTitleColor = 'limegreen'; const streamTitleFilter = 'drop-shadow(0 0 1px #00ff00) drop-shadow(0 0 2px #00ff00)' // Custom Ping Sound const customPingSound = "https://files.catbox.moe/1qbutz.mp3"; // Replace with your own link PLEASE // Sound blocking functionality const blockedSounds = [ 'https://cdn.fishtank.live/sounds/suicidebomb.mp3', 'https://cdn.fishtank.live/sounds/suicidebomb-1.mp3', 'https://cdn.fishtank.live/sounds/suicidebomb-2.mp3', 'https://cdn.fishtank.live/sounds/suicidebomb-3.mp3', 'https://cdn.fishtank.live/sounds/suicidebomb-4.mp3', 'https://cdn.fishtank.live/sounds/nuke-1.mp3', 'https://cdn.fishtank.live/sounds/nuke-2.mp3', 'https://cdn.fishtank.live/sounds/nuke-3.mp3', 'https://cdn.fishtank.live/sounds/nuke-4.mp3', 'https://cdn.fishtank.live/sounds/nuke-5.mp3', 'https://cdn.fishtank.live/sounds/horn.mp3', 'https://cdn.fishtank.live/sounds/chunk-short.mp3' ]; // List of unwanted classes to remove const unwantedClasses = [ 'mirror', 'live-stream-player_blur__7BhBE', 'live-stream-player_upside-down__YvkE4', 'chat-message-default_shrink-ray__nGvpr' ]; // Save original Audio class const OriginalAudio = window.Audio; // Create a unified Audio wrapper window.Audio = function(src) { console.log("[Tampermonkey] Attempting to play sound with src:", src); // Log the source URL // Check if the sound is a blocked one if (src && typeof src === "string" && blockedSounds.some(sound => src.includes(sound))) { console.log('Blocked sound (Audio wrapper):', src); return new OriginalAudio(); // Prevent playing blocked sound } // Check for mention.mp3 and replace with custom ping sound if (src && typeof src === "string" && src.toLowerCase().includes("mention")) { console.log("[Tampermonkey] Replacing mention sound with custom sound!", src); return new OriginalAudio(customPingSound); // Play custom ping sound instead } // Log all other sounds for debugging console.log("[Tampermonkey] Playing sound without modification:", src); // Default behavior for all other sounds return new OriginalAudio(src); }; // Keep Audio.prototype chain intact window.Audio.prototype = OriginalAudio.prototype; // Intercept fetch requests and ensure the cache doesn't block our custom sound const originalFetch = window.fetch; window.fetch = async function(resource, init) { if (typeof resource === 'string') { // Log all resources being fetched to ensure we catch the mention sound console.log("[Tampermonkey] Fetching resource:", resource); if (resource.includes('mention.mp3')) { console.log("[Tampermonkey] Replacing mention sound via fetch:", resource); return new Response(await fetch(customPingSound), { status: 200 }); } if (blockedSounds.some(sound => resource.includes(sound))) { console.log('Blocked sound (fetch):', resource); return new Response(null, { status: 403 }); } } return originalFetch(resource, init); }; // Intercept XMLHttpRequests and modify response for mention.mp3 const originalOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url) { console.log("[Tampermonkey] XMLHttpRequest opened with URL:", url); if (url.includes("mention.mp3")) { console.log("[Tampermonkey] Replacing mention sound via XHR:", url); // Override the request and prevent the original this.abort(); // Cancel the original request const customAudioRequest = new XMLHttpRequest(); customAudioRequest.open(method, customPingSound, true); customAudioRequest.send(); return; } if (blockedSounds.some(sound => url.includes(sound))) { console.log('Blocked sound (XHR):', url); this.abort(); } else { originalOpen.apply(this, arguments); } }; // Block audio elements directly (HTMLAudioElement) const originalAudioPlay = HTMLAudioElement.prototype.play; HTMLAudioElement.prototype.play = function() { console.log("[Tampermonkey] Attempting to play audio:", this.src); if (this.src.includes("mention.mp3")) { console.log("[Tampermonkey] Replacing mention sound with custom sound in HTMLAudioElement."); this.src = customPingSound; } if (blockedSounds.some(sound => this.src.includes(sound))) { console.log('Blocked sound (HTMLAudioElement):', this.src); return Promise.reject('Blocked sound'); } return originalAudioPlay.apply(this, arguments); }; setInterval(() => { const body = document.querySelector('body'); if (body) { unwantedClasses.forEach(className => { if (body.classList.contains(className)) { body.classList.remove(className); } }); } // Check if the video player is open const videoPlayer = document.querySelector('.live-stream-player_live-stream-player__4CHjG'); if (videoPlayer) { unwantedClasses.forEach(className => { const elementsWithClass = videoPlayer.querySelectorAll(`.${className}`); elementsWithClass.forEach(el => el.classList.remove(className)); if (videoPlayer.classList.contains(className)) { videoPlayer.classList.remove(className); } }); } // Check chat messages container and its children const chatContainer = document.querySelector('#chat-messages.chat-messages_chat-messages__UeL0a'); if (chatContainer) { unwantedClasses.forEach(className => { const chatElements = chatContainer.querySelectorAll(`.${className}`); chatElements.forEach(el => el.classList.remove(className)); }); } // Ensure stream title color stays updated const streamTitles = document.querySelectorAll('.live-stream_name__ngU04'); streamTitles.forEach(title => { title.style.color = streamTitleColor; title.style.filter = streamTitleFilter; }); }, 1000); function profileFix() { const profileModal = document.querySelector('.profile-modal_profile-modal__4mjE7'); if (!profileModal || profileModal.offsetParent === null) return; // Ensure modal is visible setTimeout(() => { const bio = profileModal.querySelector('.user-profile_bio__nzdwR'); const clanActions = profileModal.querySelector('.user-profile_clan-actions__aS32x'); const header = profileModal.querySelector('.user-profile_header__zP1kv'); if (!bio || !clanActions || !header) return; // Ensure required elements exist // Prevent duplicates: Check if already moved if (header.contains(bio) && header.nextElementSibling === clanActions) return; // Move bio into header, right after .user-profile_info__eFefT const userInfo = header.querySelector('.user-profile_info__eFefT'); if (userInfo && !header.contains(bio)) { bio.remove(); userInfo.insertAdjacentElement('afterend', bio); } // Move clan actions **just below** the header if (header.nextElementSibling !== clanActions) { clanActions.remove(); header.insertAdjacentElement('afterend', clanActions); } }, 100); } // Observer to detect when the profile modal appears const profileObserver = new MutationObserver(() => { const modal = document.querySelector('.profile-modal_profile-modal__4mjE7'); if (modal && modal.offsetParent !== null) { profileFix(); } }); profileObserver.observe(document.body, { childList: true, subtree: true }); // Extract logged-in username function getLoggedInUsername() { const userElement = document.querySelector('.top-bar-user_display-name__bzlpw'); return userElement ? userElement.textContent.trim() : null; } // Remove text-shadow and change font-weight for the logged-in user function styleLoggedInUserMessages() { const username = getLoggedInUsername(); if (!username) return; const messages = document.querySelectorAll('.chat-message-default_user__uVNvH'); messages.forEach(message => { if (message.textContent.includes(username)) { const userElement = message; if (userElement) { userElement.style.textShadow = 'none'; userElement.style.fontWeight = '1000'; } const messageTextElement = message.closest('.chat-message-default_chat-message-default__JtJQL').querySelector('.chat-message-default_body__iFlH4'); if (messageTextElement) { messageTextElement.style.textShadow = 'none'; messageTextElement.style.fontWeight = '1000'; } } }); } function convertUrlsToLinks(messageElement) { const urlRegex = /(\b(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}(?:\/[^\s]*)?\b)/g; const textNodes = getTextNodes(messageElement); textNodes.forEach(node => { if (urlRegex.test(node.nodeValue)) { const newContent = node.nodeValue.replace(urlRegex, function(url) { if (!url.startsWith('http://') && !url.startsWith('https://')) { const fixedUrl = `https://${url}`; return `<a href="${fixedUrl}" target="_blank">${url}</a>`; } return `<a href="${url}" target="_blank">${url}</a>`; }); const newNode = document.createElement('span'); newNode.innerHTML = newContent; node.replaceWith(newNode); } }); } function getTextNodes(element) { let textNodes = []; const walk = document.createTreeWalker(element, NodeFilter.SHOW_TEXT, null, false); let node; while (node = walk.nextNode()) { textNodes.push(node); } return textNodes; } function handleNewMessage(messageElement) { const messageTextElement = messageElement.querySelector('.chat-message-default_message__milmT'); if (messageTextElement && messageTextElement.textContent.trim()) { convertUrlsToLinks(messageTextElement); } } function waitForChatContainer() { const chatContainer = document.querySelector('.chat-messages_chat-messages__UeL0a'); if (chatContainer) { const observer = new MutationObserver((mutationsList) => { mutationsList.forEach((mutation) => { if (mutation.type === 'childList') { mutation.addedNodes.forEach((addedNode) => { if (addedNode.nodeType === 1 && addedNode.classList.contains('chat-message-default_chat-message-default__JtJQL')) { handleNewMessage(addedNode); } }); } }); }); observer.observe(chatContainer, { childList: true, subtree: true }); } else { setTimeout(waitForChatContainer, 1000); } } window.onload = function() { waitForChatContainer(); }; let isElementVisible = false; // Track visibility state // Function to change the medal size function changeMedalSize(isVisible) { const buttons = document.querySelectorAll('.medal_medal__Hqowf.medal_md__RvQMV button'); buttons.forEach(button => { if (isVisible) { button.style.setProperty('--medal-size', '32px'); } else { button.style.setProperty('--medal-size', '64px'); } }); } // Function to check if the medal selector is visible so it can fix the sizing function checkElement() { const medalSelector = document.querySelector('.medal-selector_medals__sk3PN'); if (medalSelector) { // Check if it's visible const rect = medalSelector.getBoundingClientRect(); const isVisible = rect.width > 0 && rect.height > 0; // Only change the size if visibility has changed if (isVisible !== isElementVisible) { isElementVisible = isVisible; changeMedalSize(isElementVisible); } } else { // If the selector disappears completely if (isElementVisible) { isElementVisible = false; changeMedalSize(false); } } } // check every 100ms setInterval(checkElement, 100); // Highlight messages and add glowing username for the logged-in user function highlightUserMessages() { const username = getLoggedInUsername(); if (!username) return; const messages = document.querySelectorAll('.chat-message-default_user__uVNvH'); messages.forEach(message => { if (message.textContent.includes(username)) { const chatMessage = message.closest('.chat-message-default_chat-message-default__JtJQL'); if (chatMessage && !chatMessage.classList.contains('highlighted-message')) { chatMessage.classList.add('highlighted-message'); } if (!message.classList.contains('glowing-username')) { message.classList.add('glowing-username'); } } }); } // Re-check messages every second and apply the styles setInterval(() => { highlightUserMessages(); styleLoggedInUserMessages(); }, 1000); // Custom style for the user's messages GM_addStyle(` /* This is for the site background */ body, .layout_layout__5rz87, .select_options__t1ibN { background-image: url('https://images.gamebanana.com/img/ss/mods/5f681fd055666.jpg') !important; background-size: cover !important; background-position: center !important; background-repeat: no-repeat !important; } /* This is for the chat background */ .chat_chat__2rdNg { background-image: url('https://i.imgur.com/UVjYx1I.gif') !important; background-size: cover !important; background-position: center !important; background-repeat: no-repeat !important; } /* Your text highlight color */ .highlighted-message { background-color: rgba(125, 5, 5, 0.4) !important; } /* The color your name glows in chat */ .glowing-username { -webkit-text-stroke: 1px rgba(0, 255, 0, 0.2); filter: drop-shadow(0 0 1px #00ff00) drop-shadow(0 0 2px #00ff00); } /* Header Colors */ .maejok-input-invalid, .maejok-context-message, .maejok-tts-warning-text, .chat_header__8kNPS, .top-bar_top-bar__X4p2n, .panel_body__O5yBA, .inventory_slots__D4IrC { background-color: limegreen !important; border-color: limegreen !important; } /* More header stuff */ .panel_header__T2yFW { background-color: darkgreen !important; } /* Removing dropshadow on certain text to make it look nicer */ .top-bar_top-bar__X4p2n { box-shadow: none !important; } .maejok-context-message svg path { fill: black !important; } /* This is the title of each live stream title, this is updated by the site every once in a while so its broken rn */ .live-stream_name__ngU04, { color: limegreen !important; } /* Video player Opacity */ .hls-stream-player_hls-stream-player__BJiGl, .live-stream-player_container__A4sNR, .layout_center__Vsd3b { opacity: 1; } /* Makes the Ads go away! */ .ads_ads__Z1cPk { opacity: 0; } /* Poll bottom color aka the part next to the vote button */ .poll_footer__rALdX { background-color: limegreen; } /* Poll Vote Button Disabled */ .poll_vote__b_NE0 button:disabled:hover { background-color: red !important; color: white !important; border-color: black !important; } /* Poll Vote Button Enabled */ .poll_vote__b_NE0 button:hover { background-color: red !important; color: white !important; border-color: black !important; } /* TTS & SFX Chat Messages */ .chat-message-tts_chat-message-tts__2Jlxi, .chat-message-sfx_chat-message-sfx__OGv6q { border-color: #00ff00 !important; background-color: darkgreen !important; filter: drop-shadow(0 0 2px #00ff00) drop-shadow(0 0 2px #00ff00); } /* Interior Text for TTS & SFX, Currently Glows */ .chat-message-tts_message__sWVCc, .chat-message-sfx_message__d2Rei { -webkit-text-stroke: 2px rgba(0, 255, 0, 0.6); filter: drop-shadow(0 0 2px #00ff00) drop-shadow(0 0 2px #00ff00); } /* TTS & SFX Footer Timestamp */ .chat-message-tts_timestamp__pIVv0, .chat-message-sfx_timestamp__ilYfg { color: black !important; font-weight: bold !important; text-shadow: none !important; } /* THIS IS EVERY MODAL. DONT TOUCH THE SIZE OR ALIGNMENT */ .modal_modal__MS70U { height:1000px !important; width: 1500px !important; align-self: anchor-center !important; justify-self: anchor-center !important; overflow: scroll !important; background-color: #191d21bb !important; /* The last two characters are hex code for opacity. 00 for 0%, ff for 100% */ } /* Modal Dim Background, 0% Opacity means no dimming */ .modal_backdrop__94Bu6 { opacity: 0; } /* FULL SCREEN SETTINGS MENU & ITEM DEX DO NOT TOUCH */ .settings-modal_body__qdvDm, .profile-modal_profile-modal__4mjE7 { display: flex; flex-direction: column; gap: 8px; align-items: center; margin: auto; width: 100%; padding: 16px; background-color: rgba(0, 0, 0, .25); border: 1px solid #505050; border-radius: 4px; } /* FULL SCREEN SETTINGS MENU & ITEM DEX DO NOT TOUCH */ .user-profile-tabs_tab__2bsiR { display: flex; flex-wrap: wrap; background-color: rgba(0, 0, 0, .5); padding: 8px; border: 1px solid #505050; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top: 0; gap: 4px; width: 1400px; height: 900px; justify-self: center; } /* FULL SCREEN SETTINGS MENU & ITEM DEX DO NOT TOUCH */ .user-profile-items_user-profile-items__rl_CV { display: flex; width: 1400px; height: 900px; } /* FULL SCREEN SETTINGS MENU & ITEM DEX DO NOT TOUCH */ .user-profile-items_items__zuulV { display: flex; flex-wrap: wrap; gap: 4px; padding: 8px; width: 100%; height: 100%; justify-content: space-evenly; max-height: 900px !important; } .user-profile-tts-sfx_messages__w4_Ew { max-height: 93vh !important; /* DO NOT TOUCH UNLESS YOU WANT YOUR SFX AND TTS HISTORY WINDOW BROKEN */ } .user-profile_profile__g_tBc { width: 1400px !important; /* DO NOT TOUCH UNLESS YOU WANT YOUR PROFILE AND/OR SETTINGS WINDOWS BROKEN */ max-width: 1400px !important; /* DO NOT TOUCH UNLESS YOU WANT YOUR PROFILE AND/OR SETTINGS WINDOWS BROKEN */ } .user-profile_body__hk8ZS { width: 1400px; /* DO NOT TOUCH UNLESS YOU WANT YOUR PROFILE AND/OR SETTINGS WINDOWS BROKEN */ align-content: center; /* DO NOT TOUCH UNLESS YOU WANT YOUR PROFILE AND/OR SETTINGS WINDOWS BROKEN */ } .profile-modal_profile-modal__4mjE7 { align-items: unset; /* DO NOT TOUCH UNLESS YOU WANT YOUR PROFILE AND/OR SETTINGS WINDOWS BROKEN */ } .user-profile_bio__nzdwR { padding-left: 80px; /* DO NOT TOUCH UNLESS YOU WANT YOUR PROFILE AND/OR SETTINGS WINDOWS BROKEN */ width: 1000px; /* DO NOT TOUCH UNLESS YOU WANT YOUR PROFILE AND/OR SETTINGS WINDOWS BROKEN */ } .input_input__Zwrui textarea { height: 100px; /* DO NOT TOUCH UNLESS YOU WANT YOUR PROFILE AND/OR SETTINGS WINDOWS BROKEN */ } .user-profile_header__zP1kv { width: 1400px; /* DO NOT TOUCH UNLESS YOU WANT YOUR PROFILE AND/OR SETTINGS WINDOWS BROKEN */ } .medal_medal__Hqowf.medal_md__RvQMV button { --medal-size: 64px; /* DO NOT TOUCH UNLESS YOU WANT YOUR PROFILE AND/OR SETTINGS WINDOWS BROKEN */ } .user-update-profile_actions__vbfIX button { width: 800px; /* DO NOT TOUCH UNLESS YOU WANT YOUR PROFILE AND/OR SETTINGS WINDOWS BROKEN */ } .user-update-profile_user-update-profile__sa20I { width: 1400px; /* DO NOT TOUCH UNLESS YOU WANT YOUR PROFILE AND/OR SETTINGS WINDOWS BROKEN */ } .user-update-profile_details__7bBRy { width: 350px; /* DO NOT TOUCH UNLESS YOU WANT YOUR PROFILE AND/OR SETTINGS WINDOWS BROKEN */ } .user-update-profile_bio__DaV4N { width: 800px; /* DO NOT TOUCH UNLESS YOU WANT YOUR PROFILE AND/OR SETTINGS WINDOWS BROKEN */ justify-self: flex-end; /* DO NOT TOUCH UNLESS YOU WANT YOUR PROFILE AND/OR SETTINGS WINDOWS BROKEN */ height: 200px; /* DO NOT TOUCH UNLESS YOU WANT YOUR PROFILE AND/OR SETTINGS WINDOWS BROKEN */ } .modal_body__j3Bav { align-self: anchor-center; height:100%; overflow: visible !important; } .modal_header__O0ebJ { padding-top:50px; font-size:xxx-large; } .item-generator-modal_items__Xs78_, .item-generator-modal_generator__vmam0 { background-color: rgba(14, 16, 18, 1) !important; } .logs_logs__YL0uF { width: 1400px; align-self: center; } .logs_body__lqe_U { height: 700px !important; } .logs_message__p9V2r { font-size: medium; } .sfx-modal_sfx-modal__i_ppy, .tts-modal_tts-modal__rxY0z { width: 1200px; padding-top: 150px; } .select_value__yPLpn { background-color: rgba(43, 45, 46, 1) !important; } .input_input-wrapper__xvMLO input{ background-color: rgba(43, 45, 46, 1) !important; } .user-update-profile_user-update-profile__sa20I .user-update-profile_bio__DaV4N { grid-column: 1 / 3; grid-row: 1 / 4; } .input_input-wrapper__xvMLO textarea { height: 165px; } .user-update-profile_footer__kONMY { grid-row: 2 / 6 !important; height:60px; } .user-profile-tabs_user-profile-tabs__7SFh7 { padding-top: 75px; } `); })();