Block buyee/worldshopping popups everywhere

Block buyee and worldshopping popups on all websites

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Block buyee/worldshopping popups everywhere
// @namespace    https://dakidex.com
// @match        *://*/*
// @run-at       document-start
// @grant        none
// @description  Block buyee and worldshopping popups on all websites
// @version      1.2
// @license      MIT
// ==/UserScript==

(function () {
	'use strict';

	const BLOCK_HOSTS = [
		'connect.buyee.jp',
		'worldshopping.jp',
		'shop-js.worldshopping.jp',
		'checkout-js.worldshopping.jp',
		'checkout-api.worldshopping.jp'
	];
	function isBlockedUrl(u) {
		if (!u) return false;
		try {
			const urlStr = String(u);
			return BLOCK_HOSTS.some(host => urlStr.indexOf(host) !== -1);
		} catch (e) { return false; }
	}

	// Remove any existing matching elements
	function removeExisting() {
		try {
			document.querySelectorAll('iframe,script').forEach(el => {
				const src = el.src || (el.getAttribute && el.getAttribute('src')) || '';
				if (isBlockedUrl(src)) el.remove();
			});
		} catch (e) { /* ignore */ }
	}

	// Patch Document.createElement to neutralize src assignment for iframe/script
	const origCreateElement = Document.prototype.createElement;
	Document.prototype.createElement = function (tagName, options) {
		const el = origCreateElement.call(this, tagName, options);
		const tag = String(tagName).toLowerCase();
		if (tag === 'iframe' || tag === 'script') {
			// intercept setAttribute for src/data attributes
			try {
				const origSetAttr = el.setAttribute.bind(el);
				el.setAttribute = function (name, value) {
					if ((name === 'src' || name === 'data') && isBlockedUrl(value)) return;
					return origSetAttr(name, value);
				};
			} catch (e) { /* ignore */ }

			// override property setter for .src if prototype exposes it
			try {
				const proto = Object.getPrototypeOf(el);
				const desc = Object.getOwnPropertyDescriptor(proto, 'src');
				if (desc && typeof desc.set === 'function') {
					Object.defineProperty(el, 'src', {
						configurable: true,
						enumerable: true,
						get: function () { return desc.get.call(this); },
						set: function (v) { if (isBlockedUrl(v)) return; return desc.set.call(this, v); }
					});
				}
			} catch (e) { /* ignore */ }
		}
		return el;
	};

	// Intercept DOM insertion methods to block direct appends/insertions of blocked nodes
	['appendChild', 'insertBefore', 'replaceChild'].forEach(fn => {
		const orig = Node.prototype[fn];
		if (!orig) return;
		Node.prototype[fn] = function (node, ...args) {
			try {
				if (!node) return orig.call(this, node, ...args);
				// If the node itself is a blocked iframe/script, drop it
				if (node.nodeType === 1) {
					const tag = (node.tagName || '').toLowerCase();
					if (tag === 'iframe' || tag === 'script') {
						const src = node.src || (node.getAttribute && node.getAttribute('src')) || '';
						if (isBlockedUrl(src)) return node;
					}
					// Remove nested blocked elements before insertion
					try {
						const nested = node.querySelectorAll && node.querySelectorAll('iframe,script');
						if (nested && nested.length) {
							nested.forEach(n => {
								const s = n.src || (n.getAttribute && n.getAttribute('src')) || '';
								if (isBlockedUrl(s)) n.remove();
							});
						}
					} catch (e) { /* ignore */ }
				}
			} catch (e) { /* ignore */ }
			return orig.call(this, node, ...args);
		};
	});

	// Observe DOM mutations and remove any newly added blocked frames/scripts
	const observer = new MutationObserver(mutations => {
		for (const m of mutations) {
			for (const n of m.addedNodes) {
				try {
					if (n.nodeType !== 1) continue;
					const tag = (n.tagName || '').toLowerCase();
					if (tag === 'iframe' || tag === 'script') {
						const src = n.src || (n.getAttribute && n.getAttribute('src')) || '';
						if (isBlockedUrl(src)) { n.remove(); continue; }
					}
					// remove blocked nested nodes
					const nested = n.querySelectorAll && n.querySelectorAll('iframe,script');
					if (nested && nested.length) {
						nested.forEach(el => {
							const s = el.src || (el.getAttribute && el.getAttribute('src')) || '';
							if (isBlockedUrl(s)) el.remove();
						});
					}
				} catch (e) { /* ignore */ }
			}
		}
	});
	try {
		observer.observe(document.documentElement || document, { childList: true, subtree: true });
	} catch (e) { /* ignore */ }

	// Patch existing elements' src setter defensively
	function patchExistingProps() {
		try {
			document.querySelectorAll('iframe,script').forEach(el => {
				try {
					const proto = Object.getPrototypeOf(el);
					const desc = Object.getOwnPropertyDescriptor(proto, 'src');
					if (desc && typeof desc.set === 'function') {
						Object.defineProperty(el, 'src', {
							configurable: true,
							enumerable: true,
							get: function () { return desc.get.call(this); },
							set: function (v) { if (isBlockedUrl(v)) return; return desc.set.call(this, v); }
						});
					}
				} catch (e) { /* ignore */ }
			});
		} catch (e) { /* ignore */ }
	}

	// initial cleanup (run as early as possible)
	if (document.readyState === 'loading') {
		document.addEventListener('DOMContentLoaded', () => { removeExisting(); patchExistingProps(); }, { once: true });
	} else {
		removeExisting();
		patchExistingProps();
	}
})();