B站动态自动点赞评论

270 阅读1分钟
// ==UserScript==
// @name         B站动态自动点赞评论
// @namespace    http://tampermonkey.net/
// @version      0.4
// @description  进入动态详情页后动态下的评论自动点赞
// @author       javamoss
// @match        https://www.bilibili.com/opus/*
// @icon         https://www.bilibili.com/favicon.ico
// @grant        GM_addStyle
// ==/UserScript==

(function() {
    'use strict';

    // 配置区域
    const CONFIG = {
        authorNames: ["瑞娅_Rhea"], // 需要匹配的用户名称
        scrollInterval: 1000, // 滚动间隔
        maxScrollAttempts: 5, // 最大滚动尝试次数
        checkInterval: 500 // 检查间隔
    };

    // 创建日志容器
    const logContainer = document.createElement('div');
    GM_addStyle(`
        .logger {
            position: fixed;
            bottom: 20px;
            right: 20px;
            background: rgba(0,0,0,0.8);
            color: #fff;
            padding: 10px;
            border-radius: 5px;
            max-width: 300px;
            max-height: 200px;
            overflow-y: auto;
            font-family: monospace;
            z-index: 9999;
        }
    `);
    logContainer.className = 'logger';
    document.body.appendChild(logContainer);

    // 日志记录函数
    function log(message) {
        const entry = document.createElement('div');
        entry.textContent = `[${new Date().toLocaleTimeString()}] ${message}`;
        logContainer.appendChild(entry);
        logContainer.scrollTop = logContainer.scrollHeight;
    }

    function deepQuerySelectorAll(selector, root = document) {
        const results = [];
        const searchInShadow = (node) => {
            try {
                // 在当前节点查询
                const matches = node.querySelectorAll(selector);
                if (matches.length > 0) {
                    results.push(...matches)
                }
                // 在Shadow Root中查询
                if (node.shadowRoot) {
                    searchInShadow(node.shadowRoot);
                }
                // 递归子节点
                for (const child of node.children) {
                    searchInShadow(child)
                }
            } catch (e) {
                console.warn('Shadow DOM访问异常:', e);
            }
        };
        searchInShadow(root.body || root);
        // 去重
        return Array.from(new Set(results));
    }

    // 检查作者是否匹配
    function checkAuthor() {
        const authorDiv = document.querySelector('.opus-module-author__name');
        return authorDiv && CONFIG.authorNames.includes(authorDiv.textContent.trim());
    }

    // 滚动加载全部内容
    async function fullScrollLoad() {
        let lastHeight = 0;
        let attempts = 0;

        return new Promise((resolve) => {
            const scrollInterval = setInterval(() => {
                window.scrollTo(0, document.body.scrollHeight);
                const newHeight = document.documentElement.scrollHeight;
                if (newHeight === lastHeight) {
                    if (++attempts >= CONFIG.maxScrollAttempts) {
                        clearInterval(scrollInterval);
                        resolve();
                    }
                } else {
                    lastHeight = newHeight;
                    attempts = 0;
                }
            }, CONFIG.scrollInterval);
        });
    }

    function scrollToElementCenter(element) {
        const rect = element.getBoundingClientRect();
        const centerY = rect.top + rect.height / 2 - window.innerHeight / 2;
        window.scrollBy({
            top: centerY,
            behavior: 'smooth'
        });
    }

    const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms + Math.random() * 500));

    // 执行点赞操作
    async function performLike() {
        const doms = deepQuerySelectorAll('#like button');
        log('找到' + doms.length + '个点赞按钮');
        if (!doms.length) {
            log('错误:找不到点赞按钮');
            return false;
        }
        for (let i in doms) {
            await sleep(CONFIG.checkInterval)
            const icon = doms[i].querySelector('bili-icon');
            scrollToElementCenter(doms[i])
            if (icon && icon.style.cssText.includes('--brand_blue')) {
                log('第' + (Number(i) + 1) + '个已经点赞过');
            } else {
                doms[i].click();
                log('第' + (Number(i) + 1) + '个点赞成功');
            }
        }
        log('点赞完成');
    }


    async function main() {
        if (!checkAuthor()) {
            return;
        }

        log('开始滚动加载内容...');
        await fullScrollLoad();
        log('内容加载完成,开始点赞');
        performLike();
    }

    // 启动主程序
    setTimeout(main, 2000);
})();