您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Plays audio associated with images on 4chan.
当前为
// ==UserScript== // @name 4chan External Sounds // @namespace b4k // @description Plays audio associated with images on 4chan. // @author Bakugo // @version 1.6.0 // @match *://boards.4chan.org/* // @match *://boards.4channel.org/* // @run-at document-start // ==/UserScript== (function() { var doInit; var doProcessFile; var doProcessFiles; var doPlayFile; var doMakeKey; var players; var allow; allow = [ "4cdn.org", "catbox.moe", "lewd.se" ]; document.addEventListener( "4chanXInitFinished", function (event) { doInit(); } ); doInit = function () { var observer; if (!document.documentElement.classList.contains("fourchan-x")) { return; } players = {}; doProcessFiles(document.body); observer = new MutationObserver( function (mutations) { mutations.forEach( function (mutation) { if (mutation.type === "childList") { mutation.addedNodes.forEach( function (node) { if (node.nodeType === Node.ELEMENT_NODE) { doProcessFiles(node); doPlayFile(node); } } ); } } ); } ); observer .observe( document.body, { childList: true, subtree: true } ); }; doProcessFile = function (file) { var fileLink; var fileName; var key; var match; var player; var playerSrc; var playerSrcHost; var isHostAllowed; if (!file.classList.contains("file")) { return; } fileLink = file.querySelector(".file-info > a"); if (!fileLink) { return; } fileName = null; [ file.querySelector(".file-info .fnfull"), file.querySelector(".file-info > a") ].forEach( function (node) { if (fileName) { return; } if (node && node.textContent) { fileName = node.textContent; } } ); if (!fileName) { return; } fileName = fileName.replace(/\-/, "/"); key = doMakeKey(fileLink.href); if (!key) { return; } if (players[key]) { return; } match = fileName.match(/[\[\(\{](?:audio|sound)[ \=\:\|\$](.*?)[\]\)\}]/i); if (!match) { return; } playerSrc = match[1]; if (playerSrc.includes("%")) { try { playerSrc = decodeURIComponent(playerSrc); } catch (error) { return; } } if (playerSrc.match(/^(https?\:)?\/\//) === null) { playerSrc = (location.protocol + "//" + playerSrc); } try { playerSrc = new URL(playerSrc); } catch (error) { return; } playerSrcHost = playerSrc.hostname; playerSrcHost = playerSrcHost.toLowerCase(); isHostAllowed = false; allow.forEach( function (item) { isHostAllowed = (isHostAllowed || (playerSrcHost === item)); isHostAllowed = (isHostAllowed || playerSrcHost.endsWith("." + item)); } ); if (!isHostAllowed) { return; } player = new Audio(); player.preload = "none"; player.volume = 0.80; player.loop = true; player.src = playerSrc.href; players[key] = player; }; doProcessFiles = function (target) { target.querySelectorAll(".post") .forEach( function (post) { if (post.parentElement.parentElement.id === "qp") { return; } if (post.parentElement.classList.contains("noFile")) { return; } post.querySelectorAll(".file") .forEach( function (file) { doProcessFile(file); } ); } ); }; doPlayFile = function (target) { var key; var player; var interval; if (!( target.id === "ihover" || target.className === "full-image" )) { return; } key = doMakeKey(target.src); if (!key) { return; } player = players[key]; if (!player) { return; } if (!player.paused) { if (player.dataset.play == 1) { return; } else { player.pause(); } } player.dataset.play = 1; player.dataset.moveTime = 0; player.dataset.moveLast = 0; switch (target.tagName) { case "IMG": player.loop = true; player.currentTime = 0; player.play(); break; case "VIDEO": player.loop = false; player.currentTime = target.currentTime; player.play(); break; default: return; } if (player.paused) { document.dispatchEvent( new CustomEvent( "CreateNotification", { bubbles: true, detail: { type: "warning", content: "Your browser blocked autoplay, click anywhere on the page to activate it and try again.", lifetime: 5 } } ) ); } interval = setInterval( function () { if (document.body.contains(target)) { if (target.tagName === "VIDEO") { if (target.currentTime != (+player.dataset.moveLast)) { player.dataset.moveTime = Date.now(); player.dataset.moveLast = target.currentTime; } if (player.duration != NaN) { if ( target.paused == true || target.duration == NaN || target.currentTime > player.duration || ((Date.now() - (+player.dataset.moveTime)) > 300) ) { if (!player.paused) { player.pause(); } } else { if ( player.paused || Math.abs(target.currentTime - player.currentTime) > 0.1 ) { player.currentTime = target.currentTime; } if (player.paused) { player.play(); } } } } } else { clearInterval(interval); player.dataset.play = 0; player.pause(); } }, (1000/30) ); }; doMakeKey = function (link) { var match; match = link.match(/\.(?:4cdn|4chan)\.org\/(.+?)\/(\d+?)\.(.+?)$/); if (match) { return (match[1] + "." + match[2]); } return null; }; })();