Linux.do 自动滚动工具

为 Linux.do 网站添加自动滚动功能,可缓慢滚动

// ==UserScript==
// @name         Linux.do 自动滚动工具
// @name:en      Linux.do Auto Scroller
// @name:zh-CN   Linux.do 自动滚动工具
// @namespace    https://gf.qytechs.cn/zh-TW/users/1252908-eep
// @version      1.0.9
// @description  为 Linux.do 网站添加自动滚动功能,可缓慢滚动
// @description:en  Add auto-scroll functionality to Linux.do
// @description:zh-CN  为 Linux.do 网站添加自动滚动功能,可缓慢滚动 
// @author       EEP
// @license      MIT
// @match        https://linux.do/*
// @icon         https://linux.do/favicon.ico
// @grant        none
// @run-at       document-idle
// @supportURL   https://github.com/yourusername/linux-do-autoscroller/issues
// @homepageURL  https://github.com/yourusername/linux-do-autoscroller
// ==/UserScript==

(function() {
    'use strict';

    // 滚动状态变量
    let isScrolling = false;
    let scrollInterval;
    let scrollSpeed = 3; // 每次滚动的像素数,数值越小滚动越慢
    let timer = null

    // 创建控制按钮
    let button
    function createScrollButton() {
        button = document.createElement('button');
        button.id = 'auto-scroll-button';
        button.textContent = '开始自动滚动';
        button.style.position = 'fixed';
        button.style.bottom = '20px';
        button.style.right = '20px';
        button.style.zIndex = '9999';
        button.style.padding = '8px 12px';
        button.style.backgroundColor = '#4CAF50';
        button.style.color = 'white';
        button.style.border = 'none';
        button.style.borderRadius = '4px';
        button.style.cursor = 'pointer';
        button.style.boxShadow = '0 2px 5px rgba(0,0,0,0.2)';

        // 添加速度控制滑块
        const speedControl = document.createElement('div');
        speedControl.style.position = 'fixed';
        speedControl.style.bottom = '60px';
        speedControl.style.right = '20px';
        speedControl.style.zIndex = '9999';
        speedControl.style.backgroundColor = 'white';
        speedControl.style.padding = '5px';
        speedControl.style.borderRadius = '4px';
        speedControl.style.boxShadow = '0 2px 5px rgba(0,0,0,0.2)';
        speedControl.style.display = 'flex';
        speedControl.style.flexDirection = 'column';
        speedControl.style.alignItems = 'center';

        const speedLabel = document.createElement('label');
        speedLabel.textContent = '滚动速度:';
        speedLabel.style.marginBottom = '5px';
        speedLabel.style.color = '#333';

        const speedSlider = document.createElement('input');
        speedSlider.type = 'range';
        speedSlider.min = '1';
        speedSlider.max = '10';
        speedSlider.value = scrollSpeed;
        speedSlider.style.width = '100px';

        speedSlider.addEventListener('input', function() {
            scrollSpeed = parseInt(this.value);
        });
        speedControl.appendChild(speedLabel);
        speedControl.appendChild(speedSlider);

        // 点击事件处理
        button.addEventListener('click', function() {
            if (isScrolling) {
                stopScrolling();
                button.textContent = '开始自动滚动';
                button.style.backgroundColor = '#4CAF50';
            } else {
                startScrolling();
                button.textContent = '停止自动滚动';
                button.style.backgroundColor = '#F44336';
            }
        });
        const checkBoxDiv = document.createElement('div')
        checkBoxDiv.style.marginTop = '5px'
        checkBoxDiv.style.display = 'flex'
        checkBoxDiv.style.alignItems = 'center'
        const checkBox = document.createElement('input')
        checkBox.type = 'checkbox'
        checkBox.id = 'autoscrollnext'
        checkBox.style.margin = 0
        checkBox.style.marginLeft= '5px'
        const spanText = document.createElement('label')
        spanText.setAttribute('for', 'autoscrollnext')
        spanText.style.fontSize = '14px'
        spanText.style.margin = 0
        spanText.innerText = '连续刷帖'

        checkBoxDiv.appendChild(spanText)
        checkBoxDiv.appendChild(checkBox)
        checkBox.addEventListener('change', function(event) {
            event.preventDefault();
            const checked = event.target.checked
            localStorage.setItem('ischecked', checked)
        })
        document.body.appendChild(button);
        document.body.appendChild(speedControl);
        speedControl.appendChild(checkBoxDiv);
    }

    // 自动刷
    let previousUrl = localStorage.getItem('previousUrl')
    setTimeout(function(){
        const checked = localStorage.getItem('ischecked')
        const newUrl = location.href;
        if (newUrl !== previousUrl && checked === 'true') {
            document.querySelector('#auto-scroll-button').click()
            localStorage.setItem('previousUrl', newUrl)
        }
    }, 2000);

    // 开始缓慢滚动到底部
    function startScrolling() {
        if (isScrolling) return;

        isScrolling = true;

        // 使用setInterval方法实现平滑滚动
        scrollInterval = setInterval(function() {
            // 获取当前滚动位置
            const currentPosition = window.pageYOffset || document.documentElement.scrollTop;

            // 获取文档总高度
            const totalHeight = Math.max(
                document.body.scrollHeight,
                document.body.offsetHeight,
                document.documentElement.clientHeight,
                document.documentElement.scrollHeight,
                document.documentElement.offsetHeight
            );

            // 获取视窗高度
            const windowHeight = window.innerHeight ||
                document.documentElement.clientHeight ||
                document.body.clientHeight;

            // 如果已经到达底部,停止滚动
            if (currentPosition + windowHeight + 10 >= totalHeight) {
                // 如果看到底部了,等待一段时间看是否有新内容加载
                if (timer) return
                timer = setTimeout(function(){
                   checkForNewContent(currentPosition, totalHeight)
                }, 500);
            } else {
                // 否则继续向下滚动
                window.scrollBy(0, scrollSpeed);
            }
        }, 10); // 每10毫秒滚动一次,确保平滑
    }

    // 检查是否有新内容加载
    function checkForNewContent(previousPosition, previousHeight) {
        // 获取文档高度
        const documentHeight = Math.max(
            document.body.scrollHeight,
            document.body.offsetHeight,
            document.documentElement.clientHeight,
            document.documentElement.scrollHeight,
            document.documentElement.offsetHeight
        );

        // 获取当前滚动位置
        const scrollPosition = window.scrollY + window.innerHeight;

        // 定义一个小的阈值,避免由于计算误差导致判断问题
        const threshold = 10;

        // 如果高度变化了,说明加载了新内容,继续滚动
        if (scrollPosition + threshold >= documentHeight) {
            stopScrolling()
            button.textContent = '开始自动滚动';
            button.style.backgroundColor = '#4CAF50';
            const url = findSpecificTableCellAndGetLink()
            const checked = localStorage.getItem('ischecked')
            if (url && checked === 'true') {
                window.location.href = url
            }
        }
        timer = null;
    }
    function getPreviousSiblingElement(element) {
        // 确保传入的是一个有效的元素
        if (!element || typeof element.previousElementSibling === 'undefined') {
            return null;
        }
        return element.previousElementSibling;
    }
    function findSpecificTableCellAndGetLink() {
        // Get the table with class 'topic-list'
        const table = document.querySelector('table.topic-list');

        if (!table) {
            return null; // Table not found
        }

        // Find all td elements with the specified class within the tbody
        const cells = table.querySelectorAll('tbody td.posts-map.posts.topic-list-data'); //  main-link.topic-list-data
        // Loop through each cell to check conditions
        for (const cell of cells) {
            // Check if the cell contains a span with class 'topic-post-badges'
            const badgeSpan = cell.querySelector('span.number');
            if (badgeSpan) {
                // Get the text content and convert to number
                const value = parseInt(badgeSpan.textContent.trim(), 10);
                // Check if it's a valid number and not greater than 300
                if (!isNaN(value) && value <= 300) {
                    // Find the anchor element within this cell
                    const link = cell.querySelector('a');
                    if (!link.getAttribute('href')) {
                        continue
                    }
                    const prevCell = getPreviousSiblingElement(cell)
                    const prevLink = prevCell.querySelector('a');
                    if (prevLink) {
                        return prevLink ? prevLink.getAttribute('href') : null;
                    }
                    // If link exists, return its href attribute, otherwise return the cell
                    return link ? link.getAttribute('href') : null;
                }
            }
        }

        // No matching cell found
        return null;
    }

    // 停止滚动
    function stopScrolling() {
        if (!isScrolling) return;

        clearInterval(scrollInterval);
        isScrolling = false;
    }

    // 等待页面完全加载后添加按钮
    function init() {
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', createScrollButton);
        } else {
            createScrollButton();
            // 设置checkbox
            const _checked = localStorage.getItem('ischecked')
            if (_checked) {
                document.getElementById('autoscrollnext').checked = _checked === 'true'
            }
        }
    }

    // 监听动态内容加载
    function observeDOMChanges() {
        const observer = new MutationObserver(function(mutations) {
            // 当页面内容变化时,确保我们的按钮仍然存在
            if (!document.getElementById('auto-scroll-button')) {
                createScrollButton();
            }
        });

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

    // 执行初始化
    init();
    observeDOMChanges();
})();

QingJ © 2025

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