Tiktok revanced

Auto AD Skip tiktok + 2x speed button

Bu betiği kurabilmeniz için Tampermonkey, Greasemonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

You will need to install an extension such as Tampermonkey to install this script.

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Userscripts gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği indirebilmeniz için ayrıca Tampermonkey gibi bir eklenti kurmanız gerekmektedir.

Bu komut dosyasını yüklemek için bir kullanıcı komut dosyası yöneticisi uzantısı yüklemeniz gerekecek.

(Zaten bir kullanıcı komut dosyası yöneticim var, kurmama izin verin!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Zateb bir user-style yöneticim var, yükleyeyim!)

// ==UserScript==
// @name         Tiktok revanced
// @name:pt-br   Pulador de anúncios do tiktok
// @namespace    http://tampermonkey.net/
// @version      28-12-2025
// @description:pt-br   Scrolla os anúncios do tiktok automaticamente e adiciona um botão que coloca velocidade 2x
// @description         Auto AD Skip tiktok + 2x speed button
// @author       Potly
// @match        https://www.tiktok.com/*
// @icon         https://www.tiktok.com/favicon.ico
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    const TOGGLE_KEY = "autoAdSkip_enabled";
    let enabled = localStorage.getItem(TOGGLE_KEY);
    if (enabled === null) enabled = "true";
    enabled = enabled === "true";

    function saveState() {
        localStorage.setItem(TOGGLE_KEY, enabled ? "true" : "false");
    }

    // ---------------------------
    // BOTÃO TOGGLE
    // ---------------------------
    function createToggle() {
        const wrapper = document.createElement("div");
        wrapper.style.position = "fixed";
        wrapper.style.top = "30px";
        wrapper.style.left = "170px";
        wrapper.style.zIndex = "999999";
        wrapper.style.display = "flex";
        wrapper.style.alignItems = "center";
        wrapper.style.gap = "10px";
        wrapper.style.userSelect = "none";

        // texto
        const label = document.createElement("span");
        label.textContent = "Auto AD Skip";
        label.style.fontSize = "18px";
        label.style.fontFamily = "Arial, sans-serif";
        label.style.fontWeight = "600";
        label.style.color = "#ffffff";
        wrapper.appendChild(label);

        // container do toggle
        const toggle = document.createElement("div");
        toggle.style.width = "50px";
        toggle.style.height = "26px";
        toggle.style.borderRadius = "50px";
        toggle.style.background = enabled ? "#4caf50" : "#ccc";
        toggle.style.position = "relative";
        toggle.style.cursor = "pointer";
        toggle.style.transition = "0.25s";
        toggle.style.boxShadow = "0 0 5px rgba(0,0,0,0.2)";

        // bolinha
        const knob = document.createElement("div");
        knob.style.width = "22px";
        knob.style.height = "22px";
        knob.style.background = "#fff";
        knob.style.borderRadius = "50%";
        knob.style.position = "absolute";
        knob.style.top = "2px";
        knob.style.left = enabled ? "26px" : "2px";
        knob.style.transition = "0.25s";
        knob.style.boxShadow = "0 2px 5px rgba(0,0,0,0.3)";

        toggle.appendChild(knob);
        wrapper.appendChild(toggle);
        document.body.appendChild(wrapper);

        toggle.onclick = () => {
            enabled = !enabled;
            saveState();

            // animação on e off
            toggle.style.background = enabled ? "#4caf50" : "#ccc";
            knob.style.left = enabled ? "26px" : "2px";
        };
    }

    if (document.readyState !== "loading") createToggle();
    else document.addEventListener("DOMContentLoaded", createToggle);

    // ---------------------------
    // Detecta se é ad
    // ---------------------------

    const selector = "div.css-3fgk4e-7937d88b--DivItemTagsContainer.e1d0egbk0 > div";
    const clickButtonSelector = "#main-content-homepage_hot > aside > div > div:nth-child(2) > button";

    const adKeywords = [
        "anúncio", "anuncio", "patrocinado", "patrocinada",
        "publicidade", "publi", "sponsored", "ad", "promo"
    ];

    const processed = new WeakSet();

    function isAd(el) {
        const text = (el.innerText || "").toLowerCase();
        return adKeywords.some(k => text.includes(k));
    }
 // acho q ter um delayzinho entre cada clique é bom, pq um pc ruim pode bugar

    let lastClick = 0;
function clickButton() {
    if (!enabled) return;
    const now = Date.now();
    if (now - lastClick < 500) return; // evita spam
    lastClick = now;
    const btn = document.querySelector(clickButtonSelector);
    if (btn) btn.click();

    }

    function handleNewAds() {
        document.querySelectorAll(selector).forEach(el => {
            if (processed.has(el)) return;
            if (!isAd(el)) return;

            processed.add(el);

            const io = new IntersectionObserver(entries => {
    entries.forEach(entry => {
        if (entry.isIntersecting && enabled) {
            clickButton();
            io.disconnect(); // para evitar vazamento de memoria
        }
    });
}, { threshold: 0.01 });


            io.observe(el);
        });
    }


//-----------------------------------------------------------

const SPEED_WHILE_HOLD = 2.0;
    const DEFAULT_SPEED = 1.0;

        const targetContainerSelector =
"section[class*='SectionActionBarContainer']";


//pega o vídeo que está assistindo no momento
function getCurrentVideo() {
        const videos = document.querySelectorAll("video");
        for (const v of videos) {
            const r = v.getBoundingClientRect();
            if (r.width > 0 && r.height > 0) return v;
        }
return null;
    }

function setSpeed(speed) {
        const video = getCurrentVideo();
        if (video) video.playbackRate = speed;
    }

        function createHoldButton(container) {
    if (container.querySelector("#hold-speed-wrapper")) return;

    const wrapper = document.createElement("div");
    wrapper.id = "hold-speed-wrapper";
    wrapper.style.position = "absolute";
    wrapper.style.left = "50%";
    wrapper.style.transform = "translateX(-50%)";
    wrapper.style.bottom = "100%";
    wrapper.style.marginBottom = "12px";
    wrapper.style.display = "flex";
    wrapper.style.flexDirection = "column";
    wrapper.style.alignItems = "center";
    wrapper.style.zIndex = "999999";


// ícone fast-forward (CSS)
const style = document.createElement("style");
style.textContent = `
.ff-icon {
    display: flex;
    gap: -3px;
    margin-left: 3px;
}

.ff-icon span {
    width: 0;
    height: 0;
    border-top: 8px solid transparent;
    border-bottom: 8px solid transparent;
    border-left: 12px solid white;
}
`;
document.head.appendChild(style);


    const btn = document.createElement("div");

    btn.innerHTML = `
  <div class="ff-icon">
    <span></span>
    <span></span>
  </div>
`;

    btn.style.display = "flex";
btn.style.justifyContent = "center";
btn.style.alignItems = "center";

btn.style.width = "48px";
btn.style.height = "48px";
btn.style.borderRadius = "50%";

btn.style.backgroundColor = "rgba(255, 255, 255, 0.12)";
btn.style.cursor = "pointer";

btn.style.transition = "200ms ease-in-out";
btn.style.marginTop = "8px";
btn.style.marginBottom = "6px";

btn.style.fontSize = "0px"; // igual TikTok
btn.style.userSelect = "none";


    const label = document.createElement("div");
    label.innerHTML = "<strong>2.0X</strong>";
    label.style.fontSize = "12px";
    label.style.marginTop = "4px";
    label.style.color = "rgba(255, 255, 255, 0.75)";
    label.style.opacity = "0.9";

// --- HOLD EVENTS ---
btn.addEventListener("mousedown", () => setSpeed(SPEED_WHILE_HOLD));
btn.addEventListener("mouseup", () => setSpeed(DEFAULT_SPEED));
btn.addEventListener("mouseleave", () => setSpeed(DEFAULT_SPEED));
btn.addEventListener("touchstart", () => setSpeed(SPEED_WHILE_HOLD));
btn.addEventListener("touchend", () => setSpeed(DEFAULT_SPEED));
btn.addEventListener("touchcancel", () => setSpeed(DEFAULT_SPEED));

// monta corretamente
wrapper.appendChild(btn);
wrapper.appendChild(label);

container.style.position = "relative";
container.prepend(wrapper);}


    function tryInjectButton() {
    document
        .querySelectorAll("section[class*='SectionActionBarContainer']")
        .forEach(container => {
            createHoldButton(container);
        });
}

//espera aparecer os botão do lado, pq o vídeo carrega antes doos botão e isso pode bugar a extensão se n esperar blablabla
function waitForFirstActionBar() {
    return new Promise(resolve => {
        const check = () => {
            const bar = document.querySelector(
                "section[class*='SectionActionBarContainer']"
            );
            if (bar) {
                resolve();
            } else {
                requestAnimationFrame(check);
            }
        };
        check();
    });
}

    // Observer pra feed infinito
   const mo = new MutationObserver(() => {
    tryInjectButton();
    handleNewAds();
});

mo.observe(document.body, {
    childList: true,
    subtree: true
});

// inicial
waitForFirstActionBar().then(() => {
    tryInjectButton();
    handleNewAds();
});

//evita vazamento de memoria
const io = new IntersectionObserver(entries => {
    entries.forEach(entry => {
        if (entry.isIntersecting && enabled) {
            clickButton();
            io.disconnect(); // <- IMPORTANTE
        }
    });
}, { threshold: 0.01 });


})();