Advanced AdBlocker Panel v6.13

Advanced AdBlocker with draggable panel, regex filters, counters, pause, slide toggle, safe-header rules

当前为 2025-09-01 提交的版本,查看 最新版本

// ==UserScript==
// @name         Advanced AdBlocker Panel v6.13
// @namespace    baba-scripts
// @version      6.13
// @description  Advanced AdBlocker with draggable panel, regex filters, counters, pause, slide toggle, safe-header rules
// @author       You
// @match        *://*/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addStyle
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    // ---- STORAGE KEYS ----
    const KEY_TOTAL = "adblock_total";
    const KEY_PAUSE = "adblock_paused";

    // Load values from storage
    let totalAds = GM_getValue(KEY_TOTAL, 0);
    let isPaused = GM_getValue(KEY_PAUSE, false);

    // Page counter
    let pageAds = 0;

    // ---- PANEL ----
    const panel = document.createElement("div");
    panel.id = "adblock-panel";
    panel.innerHTML = `
      <div id="ab-header">🛡️ <b>AdBlock Panel</b></div>
      <div id="ab-body">
        <div>Page Ads Blocked: <span id="ab-page">0</span></div>
        <div>Total Ads Blocked: <span id="ab-total">${totalAds}</span></div>
        <div id="ab-toggle" style="margin-top:5px; cursor:pointer; color:#00b;">
          ${isPaused ? "▶ Resume Blocking" : "⏸ Pause Blocking"}
        </div>
      </div>
    `;
    document.body.appendChild(panel);

    GM_addStyle(`
      #adblock-panel {
        position: fixed;
        top: 80px; right: 20px;
        width: 220px;
        background: #222;
        color: #fff;
        font-family: Arial, sans-serif;
        font-size: 13px;
        border-radius: 8px;
        box-shadow: 0 2px 8px rgba(0,0,0,0.6);
        z-index: 999999;
        user-select: none;
      }
      #ab-header {
        padding: 6px 10px;
        background: #333;
        border-bottom: 1px solid #444;
        cursor: move;
      }
      #ab-body {
        padding: 8px 10px;
        overflow: hidden;
        transition: max-height 0.4s ease;
        max-height: 300px;
      }
      #ab-body.collapsed {
        max-height: 0;
        padding: 0 10px;
      }
      #ab-toggle:hover { text-decoration: underline; }
    `);

    // ---- DRAGGABLE ----
    (function makeDraggable(el, handle) {
        let offsetX = 0, offsetY = 0, dragging = false;
        handle.addEventListener("mousedown", e => {
            dragging = true;
            offsetX = e.clientX - el.offsetLeft;
            offsetY = e.clientY - el.offsetTop;
        });
        document.addEventListener("mousemove", e => {
            if (!dragging) return;
            el.style.left = (e.clientX - offsetX) + "px";
            el.style.top = (e.clientY - offsetY) + "px";
            el.style.right = "auto"; // override right anchor
        });
        document.addEventListener("mouseup", () => dragging = false);
    })(panel, panel.querySelector("#ab-header"));

    // ---- COLLAPSE TOGGLE ----
    panel.querySelector("#ab-header").addEventListener("click", () => {
        panel.querySelector("#ab-body").classList.toggle("collapsed");
    });

    // ---- TOGGLE PAUSE ----
    panel.querySelector("#ab-toggle").addEventListener("click", () => {
        isPaused = !isPaused;
        GM_setValue(KEY_PAUSE, isPaused);
        panel.querySelector("#ab-toggle").textContent = isPaused ? "▶ Resume Blocking" : "⏸ Pause Blocking";
    });

    // ---- AD REMOVAL ----
    const regexRules = [
        /^ad-.*/i,
        /^-ad.*/i,
        /^ad_.*/i,
        /.*_ad$/i
    ];

    const safeTags = ["HEADER", "NAV", "FOOTER"]; // asla silme

    function matchesAdRule(str) {
        if (!str) return false;
        // Tam eşleşme (ad, ads, adverts, Ad, Ads, Adverts)
        if (/^(ad|ads|adverts)$/i.test(str)) return true;
        // Regex kuralları
        return regexRules.some(rx => rx.test(str));
    }

    function removeAds() {
        if (isPaused) return;
        let found = document.querySelectorAll("*[id], *[class]");
        let removed = 0;

        found.forEach(node => {
            if (safeTags.includes(node.tagName)) return;
            if (node.closest("#adblock-panel")) return; // paneli silme

            let id = node.id || "";
            let classes = [...node.classList];

            if (matchesAdRule(id) || classes.some(c => matchesAdRule(c))) {
                node.remove();
                pageAds++;
                totalAds++;
                removed++;
            }
        });

        if (removed > 0) {
            GM_setValue(KEY_TOTAL, totalAds);
            updateCounters();
        }
    }

    function updateCounters() {
        panel.querySelector("#ab-page").textContent = pageAds;
        panel.querySelector("#ab-total").textContent = totalAds;
    }

    // ---- RUN ----
    setInterval(removeAds, 2000);
})();