分享一个快速升级好方法(快速阅读帖子的方法)

之前2级时候,发现其他都达标了,主要就是阅读帖子两万的量少了一点点。
灵机一动,想着多刷刷帖子,后来发现拉鼠标好麻烦,就开发了一个自动滚屏的浏览器插件。
感觉挺方便,分享给大家。
zip文件,按照readme安装就行。

我用夸克网盘分享了「Auto Scroll.zip」,点击链接即可保存。打开「夸克APP」,无需下载在线播放视频,畅享原画5倍速,支持电视投屏。
链接:夸克网盘分享
提取码:pgKp


8 个赞

按一些鼠标中间,然后往下拖动一点也会自动往下滚动 :saluting_face:

1 个赞

这个很简单的呀,没必要自动化

这个插件可以后台运行,鼠标可以干其他事

1 个赞

嗯呐,这要试一下,找个很多回复的帖子,几下就刷满了 :smiling_face:

真的吗,还有这种神器啊,可怜我辛辛苦苦一个一个看帖

隐隐感觉要被和谐

有脚本的嘿嘿

佬给一个就差帖子数量了

// ==UserScript==
// @name         Linux.do 自动标记已读
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  自动将 Linux.do 论坛的帖子标记为已读
// @author       by.三文鱼
// @match        https://linux.do/*
// @grant        GM_addStyle
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_notification
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    // 使用 localStorage 存储运行状态
    const STORAGE_KEY = 'linux_do_auto_reader';
    let csrfToken = null;
    let isRunning = false;
    let lastCheckTime = 0;

    // 状态管理
    const StateManager = {
        save: () => {
            localStorage.setItem(STORAGE_KEY, JSON.stringify({
                isRunning,
                lastCheckTime: Date.now()
            }));
        },

        load: () => {
            const saved = localStorage.getItem(STORAGE_KEY);
            if (saved) {
                const data = JSON.parse(saved);
                isRunning = data.isRunning;
                lastCheckTime = data.lastCheckTime;
            }
        },

        clear: () => {
            localStorage.removeItem(STORAGE_KEY);
        }
    };

    // 添加心跳检测
    function heartbeat() {
        if (!isRunning) return;

        const now = Date.now();
        if (now - lastCheckTime > 35000) { // 如果超过35秒没有检查
            doCheck();
        }

        setTimeout(heartbeat, 5000); // 每5秒检查一次
    }

    // 获取最新的帖子列表
    async function getLastTopics() {
        try {
            const response = await fetch("https://linux.do/latest.json?no_definitions=true&page=0");
            return await response.json();
        } catch (error) {
            log(`获取帖子列表失败: ${error.message},将在3秒后刷新页面`, 'error');
            setTimeout(() => {
                window.location.reload();
            }, 3000);
            throw error;
        }
    }

    // 更新帖子为已读状态
    async function updateRead(id) {
        if (!csrfToken) {
            csrfToken = document.querySelector("meta[name=csrf-token]").content; // 首次获取并缓存 CSRF token
        }

        try {
            const response = await fetch("https://linux.do/topics/timings", {
                headers: {
                    "accept": "*/*",
                    "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
                    "x-csrf-token": csrfToken,
                    "x-requested-with": "XMLHttpRequest",
                    "x-silence-logger": "true"
                },
                referrer: `https://linux.do/t/topic/${id}`,
                referrerPolicy: "strict-origin-when-cross-origin",
                body: `timings%5B1%5D=1023&topic_time=1023&topic_id=${id}`,
                method: "POST",
                mode: "cors",
                credentials: "include"
            });

            if (response.ok) {
                console.log(`Topic ${id} marked as read successfully.`);
            } else {
                console.error(`Failed to mark topic ${id} as read. Status: ${response.status}`);
            }
        } catch (error) {
            console.error(`Error updating read status for topic ${id}:`, error);
        }
    }

    // 修改 doCheck 函数
    async function doCheck() {
        if (!isRunning) return;

        try {
            const res = await getLastTopics();
            // 添加调试日志
            console.log('获取到的帖子列表:', res.topic_list.topics);

            const unseenTopics = res.topic_list.topics.filter(topic => topic.unseen);
            // 添加调试日志
            console.log('未读帖子:', unseenTopics);

            // 更新帖子列表显示
            updateTopicsList(res.topic_list.topics);

            // 修改日志输出,显示更多信息
            if (unseenTopics.length === 0) {
                log(`获取到 ${res.topic_list.topics.length} 个帖子,其中未读帖子:0`, 'info');
            } else {
                log(`获取到 ${res.topic_list.topics.length} 个帖子,其中未读帖子:${unseenTopics.length}`, 'info');
                GM_notification({
                    title: 'Linux.do 自动阅读器',
                    text: `发现 ${unseenTopics.length} 个未读帖子`,
                    timeout: 3000
                });
            }

            for (let topic of unseenTopics) {
                if (!isRunning) break;
                log(`正在标记帖子: ${topic.id} - ${topic.title}`, 'info');
                await updateRead(topic.id);
                await new Promise(resolve => setTimeout(resolve, 3000));
            }

        } catch (error) {
            log(`获取帖子列表失败: ${error.message}`, 'error');
            console.error('完整错误信息:', error);
        }

        lastCheckTime = Date.now();
        StateManager.save();

        if (isRunning) {
            setTimeout(doCheck, 30000);
        }
    }

    // 修改帖子列表更新函数,显示已读帖子
    function updateTopicsList(topics) {
        const topicsListDiv = document.getElementById('auto-reader-topics');
        topicsListDiv.innerHTML = '';

        // 过滤出已读帖子,并最多显示10个
        const readTopics = topics.filter(topic => !topic.unseen).slice(0, 10);

        if (readTopics.length === 0) {
            const emptyMessage = document.createElement('div');
            emptyMessage.className = 'empty-message';
            emptyMessage.textContent = '暂无已读帖子';
            topicsListDiv.appendChild(emptyMessage);
            return;
        }

        readTopics.forEach(topic => {
            const topicItem = document.createElement('div');
            topicItem.className = 'topic-item read';
            topicItem.innerHTML = `
                <a href="https://linux.do/t/topic/${topic.id}" target="_blank">${topic.title}</a>
            `;
            topicsListDiv.appendChild(topicItem);
        });
    }

    // 修改初始化函数
    function init() {
        createConsole();
        StateManager.load(); // 加载保存的状态

        // 开始按钮
        document.getElementById('start-button').addEventListener('click', () => {
            if (!isRunning) {
                isRunning = true;
                StateManager.save();
                log('开始自动标记...', 'success');  // 修改为 success 类型
                updateStatusIndicator();
                doCheck();
                heartbeat();

                // 添加按钮状态反馈
                const startBtn = document.getElementById('start-button');
                startBtn.style.opacity = '0.6';
                startBtn.disabled = true;

                const stopBtn = document.getElementById('stop-button');
                stopBtn.style.opacity = '1';
                stopBtn.disabled = false;
            }
        });

        // 停止按钮
        document.getElementById('stop-button').addEventListener('click', () => {
            isRunning = false;
            StateManager.save();
            log('已停止自动标记', 'info');
            updateStatusIndicator();

            // 添加按钮状态反馈
            const startBtn = document.getElementById('start-button');
            startBtn.style.opacity = '1';
            startBtn.disabled = false;

            const stopBtn = document.getElementById('stop-button');
            stopBtn.style.opacity = '0.6';
            stopBtn.disabled = true;
        });

        // 清除日志按钮
        document.getElementById('clear-button').addEventListener('click', () => {
            const logDiv = document.getElementById('auto-reader-log');
            logDiv.innerHTML = '';
            log('日志已清除', 'info');
        });

        // 如果之前是运行状态,自动启动
        if (isRunning) {
            log('恢复自动标记...', 'info');
            doCheck();
            heartbeat();

            // 设置按钮初始状态
            const startBtn = document.getElementById('start-button');
            startBtn.style.opacity = '0.6';
            startBtn.disabled = true;

            const stopBtn = document.getElementById('stop-button');
            stopBtn.style.opacity = '1';
            stopBtn.disabled = false;
        } else {
            // 初始状态下停止按钮禁用
            const stopBtn = document.getElementById('stop-button');
            stopBtn.style.opacity = '0.6';
            stopBtn.disabled = true;
        }

        // 页面关闭前保存状态
        window.addEventListener('beforeunload', () => {
            if (isRunning) {
                StateManager.save();
            }
        });
    }

    // 页面可见性变化处理
    document.addEventListener('visibilitychange', () => {
        if (document.visibilityState === 'visible' && isRunning) {
            const now = Date.now();
            if (now - lastCheckTime > 35000) {
                doCheck(); // 如果太久没检查,立即检查
            }
        }
    });

    // 初始化
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }

    // 在 'use strict'; 后添加样式代码
    GM_addStyle(`
        #auto-reader-console {
            position: fixed;
            bottom: 20px;
            right: 20px;
            width: 320px;
            background: rgba(28, 30, 35, 0.95);
            color: #e1e1e1;
            padding: 15px;
            border-radius: 12px;
            font-size: 13px;
            z-index: 9999;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
            backdrop-filter: blur(10px);
            border: 1px solid rgba(255, 255, 255, 0.1);
            transition: all 0.3s ease;
        }

        #auto-reader-console.folded {
            width: 10px;
            padding: 10px;
            right: 0;
            border-radius: 12px 0 0 12px;
        }

        #auto-reader-console.folded #auto-reader-header {
            margin-bottom: 0;
            padding-bottom: 0;
            border-bottom: none;
        }

        #auto-reader-console.folded #auto-reader-title,
        #auto-reader-console.folded #status-indicator {
            display: none;
        }

        #fold-controls {
            display: flex;
            justify-content: center;
            align-items: center;
        }

        #auto-reader-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 10px;
            padding-bottom: 10px;
            border-bottom: 1px solid rgba(255, 255, 255, 0.1);
        }

        #auto-reader-title {
            font-weight: 600;
            font-size: 14px;
            color: #fff;
        }

        #fold-button {
            background: none;
            border: none;
            color: #fff;
            cursor: pointer;
            padding: 0;
            font-size: 14px;
        }

        #auto-reader-log {
            max-height: 150px;
            overflow-y: auto;
            margin-bottom: 12px;
            padding: 8px;
            background: rgba(0, 0, 0, 0.2);
            border-radius: 6px;
            font-size: 12px;
            line-height: 1.5;
        }

        #auto-reader-topics-container {
            margin-bottom: 12px;
        }

        .topics-title {
            font-weight: 600;
            margin-bottom: 5px;
            color: #fff;
        }

        #auto-reader-topics {
            max-height: 150px;
            overflow-y: auto;
            padding: 8px;
            background: rgba(0, 0, 0, 0.2);
            border-radius: 6px;
            font-size: 12px;
        }

        .topic-item {
            padding: 4px 0;
            border-bottom: 1px solid rgba(255, 255, 255, 0.05);
        }

        .topic-item:last-child {
            border-bottom: none;
        }

        .topic-item a {
            color: #64B5F6;
            text-decoration: none;
            display: block;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }

        .topic-item a:hover {
            text-decoration: underline;
        }

        .topic-item.unseen a {
            color: #81C784;
            font-weight: 500;
        }

        #auto-reader-log::-webkit-scrollbar,
        #auto-reader-topics::-webkit-scrollbar {
            width: 6px;
        }

        #auto-reader-log::-webkit-scrollbar-thumb,
        #auto-reader-topics::-webkit-scrollbar-thumb {
            background: rgba(255, 255, 255, 0.2);
            border-radius: 3px;
        }

        #auto-reader-controls {
            display: flex;
            gap: 8px;
        }

        .auto-reader-button {
            padding: 6px 12px;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            font-size: 12px;
            font-weight: 500;
            transition: all 0.2s ease;
            flex: 1;
            text-align: center;
            color: #fff;
        }

        #start-button {
            background: #4CAF50;
        }

        #start-button:hover {
            background: #43A047;
        }

        #stop-button {
            background: #f44336;
        }

        #stop-button:hover {
            background: #e53935;
        }

        #clear-button {
            background: #607D8B;
        }

        #clear-button:hover {
            background: #546E7A;
        }

        .success {
            color: #81C784;
            padding: 4px 0;
        }

        .error {
            color: #E57373;
            padding: 4px 0;
        }

        .info {
            color: #64B5F6;
            padding: 4px 0;
        }

        #status-indicator {
            width: 8px;
            height: 8px;
            border-radius: 50%;
            background: #f44336;
            margin-left: 8px;
            transition: background 0.3s ease;
        }

        #status-indicator.active {
            background: #4CAF50;
        }

        .auto-reader-button:disabled {
            cursor: not-allowed;
            opacity: 0.6;
        }

        #start-button:disabled {
            background: #4CAF50;
        }

        #stop-button:disabled {
            background: #f44336;
        }

        .empty-message {
            color: #888;
            text-align: center;
            padding: 10px 0;
            font-style: italic;
        }

        .topic-item.read a {
            color: #ddd;
        }
    `);

    // 修改创建控制台UI的函数
    function createConsole() {
        const console = document.createElement('div');
        console.id = 'auto-reader-console';
        console.innerHTML = `
            <div id="auto-reader-header">
                <div style="display: flex; align-items: center;">
                    <span id="auto-reader-title">Linux.do 自动阅读器</span>
                    <div id="status-indicator"></div>
                </div>
                <div id="fold-controls">
                    <button id="fold-button">◀</button>
                </div>
            </div>
            <div id="auto-reader-content">
                <div id="auto-reader-log"></div>
                <div id="auto-reader-topics-container">
                    <div class="topics-title">最近已读帖子</div>
                    <div id="auto-reader-topics"></div>
                </div>
                <div id="auto-reader-controls">
                    <button class="auto-reader-button" id="start-button">开始</button>
                    <button class="auto-reader-button" id="stop-button">停止</button>
                    <button class="auto-reader-button" id="clear-button">清除日志</button>
                </div>
            </div>
        `;
        document.body.appendChild(console);

        // 添加折叠事件监听
        document.getElementById('fold-button').addEventListener('click', toggleFold);
    }

    // 修改折叠控制函数
    function toggleFold() {
        const console = document.getElementById('auto-reader-console');
        const foldButton = document.getElementById('fold-button');
        const content = document.getElementById('auto-reader-content');

        if (console.classList.contains('folded')) {
            // 展开
            console.classList.remove('folded');
            foldButton.textContent = '◀';
            content.style.display = 'block';
        } else {
            // 折叠
            console.classList.add('folded');
            foldButton.textContent = '▶';
            content.style.display = 'none';
        }
    }

    // 添加日志函数
    function log(message, type = 'info') {
        const logDiv = document.getElementById('auto-reader-log');
        const time = new Date().toLocaleTimeString();
        const newLog = document.createElement('div');
        newLog.className = type;
        newLog.innerHTML = `[${time}] ${message}`;
        logDiv.appendChild(newLog);
        logDiv.scrollTop = logDiv.scrollHeight;
    }

    // 在 init 函数中添加状态指示器更新
    function updateStatusIndicator() {
        const indicator = document.getElementById('status-indicator');
        if (indicator) {
            indicator.className = isRunning ? 'active' : '';
        }
    }
})();

之前别人分享的

ok谢谢佬我去试试

但这玩意还没我自己水的快

佬太强了,我还是不够努力,1.8w帖子卡半个月了

佬儿无敌哈~

一直用RSS看帖,为的不用后退时看重复的贴,只看不发贴,2级3级无所谓

这是加主题数不是帖子数的吧

别人贴的代码,我还没看代码内容

推广 保存网盘有钱获得,不然一段代码。。。粘出来就是了


不是一段代码,好多代码呢?