微信读书-WEB端自动阅读插件

如果需要放在后台,请安装Chrome的Don't make me watch (https://chrome.google.com/webstore/detail/dont-make-me-watch/ahjofnjojbnikkffhagdddimbcmcphhh)插件,否则会被微信读书检测并且暂停时长累积

当前为 2021-02-12 提交的版本,查看 最新版本

// ==UserScript==
// @name         微信读书-WEB端自动阅读插件
// @namespace    http://tampermonkey.net/
// @version      2021.02.12.1
// @description 如果需要放在后台,请安装Chrome的Don't make me watch (https://chrome.google.com/webstore/detail/dont-make-me-watch/ahjofnjojbnikkffhagdddimbcmcphhh)插件,否则会被微信读书检测并且暂停时长累积
// @author       纯白约定
// @grant        纯白约定
// @include https://weread.qq.com/web/reader/*
// @require https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js

// ==/UserScript==
/* global $ */

/**
 * 开启模拟阅读任务
 */
function startInterval() {
    if (window.timerScroll == null) {
        window.timerScroll = setInterval(function () {
            const top = window.$document.scrollTop();

            if (top === 0) { window.stepFlag = 1 }

            window.scrollOffset += window.stepFlag * window.offsetStep
            // 模拟滚动条
            window.$document.scrollTop(window.scrollOffset)

            // scroll后scrollTop不变,则可以切换scroll方向了
            if (top == window.$document.scrollTop()) { window.stepFlag = -1 }
        }, 2000)
    }

    // 开启翻页定时任务,每 20分钟翻下一页
    if (window.timerSwitchPage == null) {
        window.timerSwitchPage = setInterval(function () {
            // 获取翻页方向标识值
            const directionVal = checkAndComputeDirection()
            console.log(directionVal)

            // 37为左翻页,39为右翻页
            let keyEventCode = (directionVal === -1) ? 37 : 39;

            // 此时这里应该判断是否为第一章/最终章,方便往回看,形成阅读闭环
            fireKeyEvent(document, 'keydown', keyEventCode);
        }, 1200000)
    }
}

/**
 * 关闭模拟阅读任务
 */
function stopInterval() {
    if (window.timerScroll != null) {
        clearInterval(window.timerScroll)
        window.timerScroll = null
    }

    if (window.timerSwitchPage != null) {
        clearInterval(window.timerSwitchPage)
        window.timerSwitchPage = null
    }
}

window.isEnabled = false

/**
 * 模拟触发 按键 事件
 *
 * @param {object} el
 * @param {string} evtType
 * @param {number} keyCode
 */
function fireKeyEvent(el, evtType, keyCode) {
    let evtObj;
    if (document.createEvent) {
        // firefox 浏览器下模拟事件
        if (window.KeyEvent) {
            evtObj = document.createEvent('KeyEvents');
            evtObj.initKeyEvent(evtType, true, true);
            el.dispatchEvent(evtObj)
            return
        }

        // chrome 浏览器下模拟事件
        evtObj = document.createEvent('UIEvents');
        evtObj.initUIEvent(evtType, true, true);

        delete evtObj.keyCode;
        //为了模拟keycode
        if (typeof evtObj.keyCode === "undefined") {
            Object.defineProperty(evtObj, "keyCode", { value: keyCode });
        } else {
            evtObj.key = String.fromCharCode(keyCode);
        }

        if (typeof evtObj.ctrlKey === 'undefined') {//为了模拟ctrl键
            Object.defineProperty(evtObj, "ctrlKey", { value: true });
        } else {
            evtObj.ctrlKey = true;
        }

        el.dispatchEvent(evtObj);
        return
    }

    //IE 浏览器下模拟事件
    if (document.createEventObject) {
        evtObj = document.createEventObject();
        evtObj.keyCode = keyCode
        el.fireEvent('on' + evtType, evtObj);
    }
}

/**
 * 根据开关状态 - 开启/关闭 模拟阅读任务
 *
 * @param {bool} isEnabled
 */
function handleInterval(isEnabled) {
    if (isEnabled) {
        startInterval()
        return
    }

    stopInterval()
}

/**
* 根据插件状态获取对应配置信息
*/
window.fetchStatusConfig = function (isEnabled) {
    const statusMap = {
        on: {
            label: 'On 🧐',
            style: {
                fontWeight: 'bolder',
                color: 'red',
            },
        },
        off: {
            label: 'Off 😴',
            style: {
                fontWeight: '',
                color: '#ffffff',
            }
        },
    }

    return isEnabled ? statusMap.on : statusMap.off
}

/**
 * direction为翻页方向 1为往后翻 -1为往前翻
 */
/**
 * 根据页面元素决定当前翻页方向
 */
window.direction = 1
function checkAndComputeDirection() {
    const directionRight = 1
    const directionLeft = -1
    // 首页的标记元素,有该元素标识已经到达第一页
    const startElement = $('.bookInfo_title')
    if (startElement.length) {
        window.direction = directionRight
        return directionRight
    }

    // 尾页的标记元素,有该元素标识已经到达最后一页
    const endElement = $('.readerFooter_ending')
    if (endElement.length) {
        window.direction = directionLeft
        return directionLeft
    }

    return window.direction
}

/**
 *
 * 初始化UI元素
 *
 * @param {object} $body
 */
function initUIElement($body) {
    const statusOff = window.fetchStatusConfig(window.isEnabled)
    $body.append('<span id="switch" title="点击切换阅读状态" style="font-size: 20px;opacity: 0.7;position: fixed;z-index: 1024;top: 100px;right: 100px;/* width: 100px; *//* height: 50px; */cursor: pointer;">' + statusOff.label + '</span>');

    $('#switch').on('click', function () {
        window.isEnabled = !window.isEnabled
        const statusNew = window.fetchStatusConfig(window.isEnabled)

        Object.assign(this.style, statusNew.style)
        this.textContent = statusNew.label

        handleInterval(window.isEnabled)
    })
}

/**
 * 启动脚本
 */
(function () {
    'use strict';

    window.$body = $('body')
    window.$document = $(document)

    window.scrollOffset = 0
    window.stepFlag = 1

    window.offsetStep = 1
    initUIElement(window.$body);
})();

QingJ © 2025

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