油猴脚本实现抖音直播间自动屏蔽礼物信息和特效

作者头像

原因
事情是这样的...抖音网页直播进入直播间后 送礼信息、福袋口令、礼物特效 都很影响观看直播效果,然后大佬出手搞定了它
废话不多说了 直接上代码 也有 @Zker(The-rapist) 大佬协助
效果预览图
进入直播间后会自动点击,然后关闭悬浮窗... 快去试试吧.
代码

// ==UserScript==
// @name         抖音直播自动设置
// @namespace    https://live.douyin.com/660292215268
// @version      1.0
// @description  自动关闭送礼信息、福袋口令和礼物特效
// @author       By Zker(The-rapist)、anwen
// @match        *://*.douyin.com/*
// @icon         https://lf3-static.bytednsdoc.com/obj/eden-cn/666eh7nuhfvhpebd/douyin_web/douyin_web/pwa_v3/512_512.png
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    console.log('[抖音直播自动设置] 脚本已加载');

    // 等待页面完全加载
    function waitForPageLoad() {
        return new Promise((resolve) => {
            if (document.readyState === 'complete') {
                resolve();
            } else {
                window.addEventListener('load', resolve);
            }
        });
    }

    // 等待元素出现
    function waitForElement(selector, timeout = 120000) {
        return new Promise((resolve, reject) => {
            console.log(`[等待元素] 查找: ${selector}`);

            const element = document.querySelector(selector);
            if (element) {
                console.log(`[等待元素] 立即找到: ${selector}`);
                resolve(element);
                return;
            }

            const observer = new MutationObserver((mutations, obs) => {
                const element = document.querySelector(selector);
                if (element) {
                    console.log(`[等待元素] 观察到: ${selector}`);
                    obs.disconnect();
                    resolve(element);
                }
            });

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

            setTimeout(() => {
                observer.disconnect();
                reject(new Error(`等待元素超时: ${selector}`));
            }, timeout);
        });
    }

    // 模拟 React 悬浮事件
    function hoverReactElement(element) {
        console.log('[悬浮元素]', element);

        // 触发 React 能够监听的悬浮相关事件
        const hoverEvents = [
            'mouseenter',  // 鼠标进入元素
            'mouseover',   // 鼠标移动到元素上(冒泡)
            'mousemove'    // 鼠标在元素上移动
        ];

        hoverEvents.forEach(eventType => {
            const event = new MouseEvent(eventType, {
                view: window,
                bubbles: true,
                cancelable: true,
                clientX: 0,
                clientY: 0,
                buttons: 0  // 没有按钮按下
            });
            element.dispatchEvent(event);
        });

        // 也触发 pointer 悬浮事件
        const pointerHoverEvents = ['pointerenter', 'pointerover', 'pointermove'];
        pointerHoverEvents.forEach(eventType => {
            const event = new PointerEvent(eventType, {
                view: window,
                bubbles: true,
                cancelable: true,
                isPrimary: true,
                clientX: 0,
                clientY: 0,
                buttons: 0  // 没有按钮按下
            });
            element.dispatchEvent(event);
        });
    }

    // 移除悬浮状态
    function unhoverReactElement(element) {
        console.log('[移除悬浮]', element);

        // 触发鼠标离开事件
        const leaveEvents = [
            'mouseleave',  // 鼠标离开元素
            'mouseout'     // 鼠标移出元素(冒泡)
        ];

        leaveEvents.forEach(eventType => {
            const event = new MouseEvent(eventType, {
                view: window,
                bubbles: true,
                cancelable: true,
                clientX: 0,
                clientY: 0,
                buttons: 0
            });
            element.dispatchEvent(event);
        });

        // 也触发 pointer 离开事件
        const pointerLeaveEvents = ['pointerleave', 'pointerout'];
        pointerLeaveEvents.forEach(eventType => {
            const event = new PointerEvent(eventType, {
                view: window,
                bubbles: true,
                cancelable: true,
                isPrimary: true,
                clientX: 0,
                clientY: 0,
                buttons: 0
            });
            element.dispatchEvent(event);
        });
    }

    // 模拟 React 点击事件
    function clickReactElement(element) {
        console.log('[点击元素]', element);

        // 触发多种事件以确保 React 能够捕获
        const events = ['mousedown', 'mouseup', 'click'];

        events.forEach(eventType => {
            const event = new MouseEvent(eventType, {
                view: window,
                bubbles: true,
                cancelable: true,
                buttons: 1
            });
            element.dispatchEvent(event);
        });

        // 也尝试触发 pointer 事件
        const pointerEvents = ['pointerdown', 'pointerup'];
        pointerEvents.forEach(eventType => {
            const event = new PointerEvent(eventType, {
                view: window,
                bubbles: true,
                cancelable: true,
                isPrimary: true
            });
            element.dispatchEvent(event);
        });
    }

    // 等待一段时间
    function sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    // 查找并关闭开关
    async function toggleOffSwitches() {
        try {
            console.log('[关闭开关] 开始查找送礼信息和福袋口令的开关');

            // 等待设置面板出现
            await sleep(10);

            // 查找所有包含开关的容器
            const allContainers = document.querySelectorAll('.R8qN4fs1');

            console.log(`[关闭开关] 找到 ${allContainers.length} 个容器`);

            // 遍历所有容器,查找包含"送礼信息"和"福袋口令"的容器
            for (const container of allContainers) {
                const textContent = container.textContent || '';

                // 如果容器包含"送礼信息"或"福袋口令"文字
                if (textContent.includes('送礼信息') || textContent.includes('福袋口令')) {
                    console.log('[关闭开关] 找到包含送礼信息/福袋口令的容器');

                    // 查找该容器内的所有行
                    const rows = container.querySelectorAll('.tvFMszYY');

                    for (const row of rows) {
                        const rowText = row.textContent || '';

                        // 只处理"送礼信息"和"福袋口令"这两行
                        if (rowText.includes('送礼信息') || rowText.includes('福袋口令')) {
                            console.log(`[关闭开关] 处理: ${rowText.includes('送礼信息') ? '送礼信息' : '福袋口令'}`);

                            // 查找该行内的开关
                            const switchElement = row.querySelector('.dNuSIvAp.SpsbqNUm.cA0AmKoK');

                            if (switchElement) {
                                // 检查开关是否已经关闭(通过检查是否有 cA0AmKoK 类)
                                // cA0AmKoK 表示开关是开启的状态
                                const isOn = switchElement.classList.contains('cA0AmKoK');

                                console.log(`[关闭开关] ${rowText.includes('送礼信息') ? '送礼信息' : '福袋口令'} 状态: ${isOn ? '开启' : '关闭'}`);

                                // 如果开关是开启状态,点击关闭
                                if (isOn) {
                                    console.log(`[关闭开关] 点击关闭 ${rowText.includes('送礼信息') ? '送礼信息' : '福袋口令'}`);
                                    clickReactElement(switchElement);
                                    await sleep(10);
                                }
                            } else {
                                console.error('[关闭开关] 未找到开关元素');
                            }
                        }
                    }
                }
            }

            console.log('[关闭开关] 送礼信息和福袋口令处理完成');
            return true;
        } catch (error) {
            console.error('[关闭开关] 操作失败:', error);
            return false;
        }
    }

    // 主执行流程
    async function main() {
        try {
            console.log('[主流程] 等待页面加载完成...');
            await waitForPageLoad();
            console.log('[主流程] 页面已加载');

            // 等待额外的时间确保所有元素都渲染完成
            await sleep(10);

            // 步骤1: 悬浮弹幕设置图标
            console.log('[步骤1] 查找弹幕设置图标...');
            const danmakuIcon = await waitForElement('div[data-e2e="danmaku-setting-icon"]');

            if (danmakuIcon) {
                console.log('[步骤1] 找到弹幕设置图标,准备悬浮');
                hoverReactElement(danmakuIcon);
                console.log('[步骤1] 已悬浮弹幕设置图标');
            } else {
                console.error('[步骤1] 未找到弹幕设置图标');
                return;
            }

            // 等待设置面板打开
            await sleep(10);

            // 步骤2: 关闭送礼信息和福袋口令
            console.log('[步骤2] 开始关闭送礼信息和福袋口令...');
            await toggleOffSwitches();

            // 等待一下
            await sleep(10);

            // 步骤3: 悬浮礼物设置图标
            console.log('[步骤3] 查找礼物设置图标...');
            const giftIcon = await waitForElement('div[data-e2e="gift-setting"]');

            if (giftIcon) {
                console.log('[步骤3] 找到礼物设置图标,准备悬浮');
                hoverReactElement(giftIcon);
                console.log('[步骤3] 已悬浮礼物设置图标');
            } else {
                console.error('[步骤3] 未找到礼物设置图标');
                return;
            }

            // 等待礼物设置面板打开
            await sleep(10);

            // 步骤4: 开启"屏蔽礼物特效"
            console.log('[步骤4] 开始开启屏蔽礼物特效...');

            // 等待礼物设置面板完全加载
            await sleep(10);

            // 直接通过 data-e2e 属性查找屏蔽礼物特效开关
            const effectSwitch = await waitForElement('div[data-e2e="effect-switch"]');

            if (effectSwitch) {
                console.log('[步骤4] 找到屏蔽礼物特效开关');

                // 查找开关元素
                const switchElement = effectSwitch.querySelector('.dNuSIvAp.EkEDO2Hs');

                if (switchElement) {
                    // 检查开关是否已经开启(根据你提供的HTML,关闭状态是 EkEDO2Hs,开启状态应该有额外的类)
                    // 我们需要检查是否有 cA0AmKoK 类或其他表示开启的类
                    const isOn = switchElement.classList.contains('cA0AmKoK') ||
                                 switchElement.querySelector('.Cri3cNdU.gDrxzyfK') !== null;

                    console.log(`[步骤4] 屏蔽礼物特效 状态: ${isOn ? '开启' : '关闭'}`);

                    // 如果开关是关闭状态,点击开启
                    if (!isOn) {
                        console.log('[步骤4] 点击开启 屏蔽礼物特效');
                        clickReactElement(switchElement);
                        await sleep(10);
                    } else {
                        console.log('[步骤4] 屏蔽礼物特效 已经是开启状态,无需操作');
                    }
                } else {
                    console.error('[步骤4] 未找到屏蔽礼物特效开关元素');
                }
            } else {
                console.error('[步骤4] 未找到屏蔽礼物特效开关容器');
            }

            // 步骤5: 移除所有悬浮状态
            console.log('[步骤5] 开始移除悬浮状态...');
            await sleep(10);

            // 移除礼物设置图标的悬浮状态
            if (giftIcon) {
                console.log('[步骤5] 移除礼物设置图标悬浮状态');
                unhoverReactElement(giftIcon);
            }

            await sleep(10);

            // 移除弹幕设置图标的悬浮状态
            if (danmakuIcon) {
                console.log('[步骤5] 移除弹幕设置图标悬浮状态');
                unhoverReactElement(danmakuIcon);
            }

            console.log('[主流程] ✅ 所有设置已完成');

        } catch (error) {
            console.error('[主流程] 执行出错:', error);
        }
    }

    // 启动脚本
    console.log('[抖音直播自动设置] 准备执行主流程...');
    main();
})();

51cda9bcccdc075d6e491794389fb8f4_225901t4jy6ir42o842t3h.webp

本站资源仅供学习交流使用请勿商业运营,严禁使用模板&源码从事违法,侵权等非法活动!如链接失效内容有误,请到评论反馈。

免费声明

  1. 本网站的文章内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长QQ:304906607进行删除处理。
  2. 文章采用: 《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)。
  3. 本站资源大多存储在云盘,如发现链接失效,请联系我们我们会第一时间更新。
  4. 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
  5. 本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
  6. 本站永久网址:https://www.aybk.cn
vFlat Scan v1.14.0 高效解锁版:智能书本扫描与OCR转换工具
« 上一篇 12-17
高清速成!一网打尽70套抖音快手爆款封面模板
下一篇 » 12-17

发表评论

请先登录后才能发表评论

没有更多评论了

个人信息

HI好朋友 ! 请登录
开通会员,享受下载全站资源特权。
百度一下

随便看看

大家都在看

2025年 乙巳年 蛇年
13 : 36 : 00
公历日期
9月26日
农历日期
八月初五
星期
星期五
下午好
金秋时节,愿您收获满满
距离国庆节还有5天
登陆
还没有账号?立即注册
点击按钮进行验证
忘记密码?
登陆
忘记密码
已经有账号?马上登陆
获取验证码
重新获取(60s)
点击按钮进行验证
重置密码
注册
已经有账号?马上登陆
获取验证码
重新获取(60s)
点击按钮进行验证
立即注册