TikTok Auto Like

Automatically clicks the like button on TikTok live pages with a draggable and collapsible UI.

// ==UserScript==
// @name         TikTok Auto Like
// @namespace    http://tampermonkey.net/
// @version      1.9
// @description  Automatically clicks the like button on TikTok live pages with a draggable and collapsible UI.
// @author       therealbeanos.
// @match        https://www.tiktok.com/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    let intervalId = null;
    let clickInterval = 200;
    let isMinimized = false;
    let isDragging = false;
    let offsetX, offsetY;
    let rateLimited = false;

    function autoClickLikeButton() {
        const likeButtonContainer = document.querySelector('.css-hm4yna-DivLikeContainer.ebnaa9i0');
        if (likeButtonContainer) {
            const likeButton = likeButtonContainer.querySelector('.css-1mk0i7a-DivLikeBtnIcon.ebnaa9i3');
            if (likeButton && !rateLimited) {
                likeButton.click();
            }
        }
    }

    function startAutoClicking() {
        if (!intervalId) {
            intervalId = setInterval(autoClickLikeButton, clickInterval);
            const startButton = document.getElementById('start-button');
            const stopButton = document.getElementById('stop-button');
            if (startButton) startButton.style.backgroundColor = '#00f593';
            if (stopButton) stopButton.style.backgroundColor = '';
            updateLiveStatus('Live', '#00f593');
        }
    }

    function stopAutoClicking() {
        if (intervalId) {
            clearInterval(intervalId);
            intervalId = null;
            const startButton = document.getElementById('start-button');
            const stopButton = document.getElementById('stop-button');
            if (stopButton) stopButton.style.backgroundColor = '#ff2d55';
            if (startButton) startButton.style.backgroundColor = '';
            updateLiveStatus('Stopped', '#ff2d55');
        }
    }

    function updateLiveStatus(status, color) {
        const statusElement = document.getElementById('live-status');
        const rateLimitMessage = document.getElementById('rate-limit-message');
        if (statusElement) {
            statusElement.textContent = `Status: ${status}`;
            statusElement.style.color = color;
            statusElement.style.textAlign = 'center';
        }
        if (rateLimitMessage) {
            rateLimitMessage.style.textAlign = 'center';
        }
    }

    function createUI() {
        const uiContainer = document.querySelector('#auto-click-ui');
        if (!uiContainer) {
            const uiContainer = document.createElement('div');
            uiContainer.id = 'auto-click-ui';
            uiContainer.style.position = 'absolute';
            uiContainer.style.top = '50px';
            uiContainer.style.right = '10px';
            uiContainer.style.backgroundColor = '#ffffff';
            uiContainer.style.border = '1px solid #ddd';
            uiContainer.style.borderRadius = '8px';
            uiContainer.style.boxShadow = '0 4px 6px rgba(0, 0, 0, 0.1)';
            uiContainer.style.padding = '15px';
            uiContainer.style.zIndex = 1000;
            uiContainer.style.fontFamily = 'Arial, sans-serif';
            uiContainer.style.fontSize = '14px';
            uiContainer.style.color = '#333';
            uiContainer.style.transition = 'max-height 0.3s ease';
            uiContainer.style.overflow = 'hidden';

            uiContainer.innerHTML = `
                <div style="text-align: center; margin-bottom: 15px; font-family: 'Arial', sans-serif;">
                    <span style="font-size: 18px; font-weight: bold; color: #333;">TikTok</span><br>
                    <span style="font-size: 24px; font-weight: bold; color: #ff2d55;">Auto Like</span>
                </div>
                <div style="display: flex; justify-content: space-between; margin-bottom: 10px;">
                    <button id="start-button" style="flex: 1; margin-right: 5px; padding: 8px 12px; background-color: #fff; border: 1px solid #ddd; border-radius: 4px; cursor: pointer;">Start</button>
                    <button id="stop-button" style="flex: 1; margin-left: 5px; padding: 8px 12px; background-color: #fff; border: 1px solid #ddd; border-radius: 4px; cursor: pointer;">Stop</button>
                </div>
                <div>
                    <label for="interval-input" style="display: block; margin-bottom: 5px; font-weight: bold;">Interval (ms):</label>
                    <input type="number" id="interval-input" value="${clickInterval}" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px;">
                </div>
                <div id="live-status" style="margin-top: 10px; color: #ff2d55; font-weight: bold; text-align: center;">Status: Stopped</div>
                <div id="rate-limit-message" style="color: #ff2d55; font-weight: bold; margin-top: 10px; display: none; text-align: center;">Rate limit exceeded. Please wait...</div>
            `;

            const heartIcon = document.createElement('div');
            heartIcon.style.width = '24px';
            heartIcon.style.height = '24px';
            heartIcon.style.backgroundSize = 'cover';
            heartIcon.style.margin = '0 auto 10px';
            uiContainer.insertBefore(heartIcon, uiContainer.firstChild);

            document.body.appendChild(uiContainer);

            uiContainer.addEventListener('mousedown', (e) => {
                isDragging = true;
                offsetX = e.clientX - uiContainer.offsetLeft;
                offsetY = e.clientY - uiContainer.offsetTop;
            });

            document.addEventListener('mousemove', (e) => {
                if (isDragging) {
                    uiContainer.style.left = `${e.clientX - offsetX}px`;
                    uiContainer.style.top = `${e.clientY - offsetY}px`;
                    uiContainer.style.right = 'auto';
                }
            });

            document.addEventListener('mouseup', () => {
                isDragging = false;
            });

            const expandBar = document.createElement('div');
            expandBar.style.width = '50%';
            expandBar.style.height = '10px';
            expandBar.style.backgroundColor = '#000';
            expandBar.style.cursor = 'pointer';
            expandBar.style.borderRadius = '0 0 8px 8px';
            expandBar.style.position = 'absolute';
            expandBar.style.left = '25%';
            expandBar.style.bottom = '0';
            uiContainer.appendChild(expandBar);

            expandBar.addEventListener('click', () => {
                isMinimized = !isMinimized;
                if (isMinimized) {
                    uiContainer.style.maxHeight = '50px';
                    expandBar.style.display = 'block';
                } else {
                    uiContainer.style.maxHeight = '300px';
                    expandBar.style.display = 'block';
                }
            });

            document.getElementById('start-button').addEventListener('click', () => {
                const inputValue = parseInt(document.getElementById('interval-input').value, 10);
                if (!isNaN(inputValue) && inputValue > 0) {
                    clickInterval = inputValue;
                    if (intervalId) {
                        stopAutoClicking();
                        startAutoClicking();
                    }
                }
                startAutoClicking();
            });

            document.getElementById('stop-button').addEventListener('click', stopAutoClicking);
        }
    }

    function checkRateLimit() {
        const originalFetch = window.fetch;
        window.fetch = async function (...args) {
            const response = await originalFetch(...args);
            if (response.status === 429) {
                rateLimited = true;
                document.getElementById('rate-limit-message').style.display = 'block';
                updateLiveStatus('Rate limited, please wait...', '#ff2d55');
            } else {
                rateLimited = false;
                document.getElementById('rate-limit-message').style.display = 'none';
            }
            return response;
        };
    }

    window.addEventListener('load', () => {
        createUI();
        checkRateLimit();
    });
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址