YoutubeDLC

YouTube独轮车

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

Advertisement:

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

Advertisement:

// ==UserScript==
// @name         YoutubeDLC
// @description  YouTube独轮车
// @namespace    http://tampermonkey.net/
// @version      2026-07-17-3:08
// @author       奶糖花的绿冻兄弟
// @match https://www.youtube.com/watch*
// @match https://www.youtube.com/live_chat*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        GM_setValue
// @grant        GM_addValueChangeListener
// @license      MIT
// ==/UserScript==


(function() {
    'use strict';


    if (location.pathname === "/watch") {


        const observer = new MutationObserver(() => {

            if (document.querySelector("ytd-live-chat-frame")) {

                observer.disconnect();

                const panel = createPanel();

                createToggle(panel);

            }

        });

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

    }

    if (location.pathname === "/live_chat") {
        GM_addValueChangeListener("SM2RR", (name, oldValue, newValue) => {
            sendMessageToRealChatRoom(newValue.msg);
        });
    }

    function createToggle(panel){

        const toggleBtn = document.createElement("button");

        toggleBtn.textContent = "独轮车";
        toggleBtn.style.display = "flex";
        toggleBtn.style.justifyContent = "center"; // 水平居中
        toggleBtn.style.alignItems = "center";// 垂直居中
        toggleBtn.style.position = "fixed";
        toggleBtn.style.right = "0px";
        toggleBtn.style.bottom = "5px";
        toggleBtn.style.width = "60px";
        toggleBtn.style.height = "25px";
        toggleBtn.style.cursor = "pointer";
        toggleBtn.style.backgroundColor = "red";
        toggleBtn.style.zIndex = 999999;
        toggleBtn.style.display = "flex";

        toggleBtn.onclick = () => {

            if (panel.style.display === "none") {
                panel.style.display = "flex"
            }else{
                panel.style.removeProperty("left");
                panel.style.removeProperty("top");

                panel.style.right = "20px";
                panel.style.bottom = "35px";
            }

        };


        document.body.appendChild(toggleBtn);

    }

    function createPanel(){
        const Panel = document.createElement("div");
        Panel.style.position = "fixed";
        Panel.style.right = "20px";
        Panel.style.bottom = "35px";
        Panel.style.width = "280px";
        Panel.style.background = "#222";
        Panel.style.color = "white";
        Panel.style.padding = "0px";
        Panel.style.borderRadius = "0px";
        Panel.style.display = "none";
        Panel.style.flexDirection = "column";
        Panel.style.zIndex = 999999;

        const TopRow = document.createElement("div");
        TopRow.style.display = "flex";
        TopRow.style.width = "100%";

        const title = document.createElement("div");
        title.textContent = "YouTube DLC";
        title.style.cursor = "move";
        title.style.padding = "8px";
        title.style.background = "red";
        title.style.flex = "0.9";

        const btnHide = document.createElement("button");
        btnHide.textContent = "-";
        btnHide.style.flex = "0.1";

        btnHide.onclick = () => {

            Panel.style.display = "none";

        };

        TopRow.append(title, btnHide);

        Panel.prepend(TopRow);

        //panel move

        let dragging = false;
        let offsetX = 0;
        let offsetY = 0;

        const mask = document.createElement("div");
        mask.style.position = "fixed";
        mask.style.left = "0";
        mask.style.top = "0";
        mask.style.width = "100vw";
        mask.style.height = "100vh";
        mask.style.zIndex = "999998";
        mask.style.background = "transparent";

        title.addEventListener("pointerdown", (e) => {

            document.body.appendChild(mask);
            dragging = true;

            const rect = Panel.getBoundingClientRect();

            // 转换为 left/top 定位
            Panel.style.left = rect.left + "px";
            Panel.style.top = rect.top + "px";

            Panel.style.right = "auto";
            Panel.style.bottom = "auto";

            offsetX = e.clientX - rect.left;
            offsetY = e.clientY - rect.top;

            e.preventDefault();
        });


        document.addEventListener("pointermove", (e) => {

            if (!dragging) return;

            Panel.style.left = (e.clientX - offsetX) + "px";
            Panel.style.top = (e.clientY - offsetY) + "px";

        });


        document.addEventListener("pointerup", () => {

            dragging = false;

            mask.remove();
        });

        //






        const pageDlc= createDlcUI();

        const pageRandomDlc = createRandomDlcUI();

        const menu = createMenuUI(pageDlc,pageRandomDlc);

        Panel.appendChild(menu);

        Panel.appendChild(pageDlc);
        Panel.appendChild(pageRandomDlc);



        document.body.appendChild(Panel);

        return Panel;
    }

    function createMenuUI(page1,page2){
        const menu = document.createElement("div");
        menu.style.padding = "10px 10px 5px 10px";
        menu.style.display = "flex";
        menu.style.borderBottom = "1px solid #555";

        const btnDLC = document.createElement("button");
        btnDLC.textContent = "独轮车";

        const btnAuto = document.createElement("button");
        btnAuto.textContent = "敬請期待";

        const btnSetting = document.createElement("button");
        btnSetting.textContent = "敬請期待";

        [btnDLC, btnAuto, btnSetting].forEach(btn => {

            btn.style.flex = "1";// 平分宽度
            btn.style.padding = "8px";
            btn.style.cursor = "pointer";

        });

        btnDLC.onclick = () => {
            changeShowHide(page1,page2);
        };

        btnAuto.onclick = () => {
            changeShowHide(page2,page1);
        };

        btnSetting.onclick = () => {
        };


        menu.append(btnDLC, btnAuto, btnSetting);

        return menu;
    }

    function createDlcUI() {
        //panel
        const pageDLC = document.createElement("div");
        pageDLC.style.padding = "5px 10px 10px 10px";
        pageDLC.style.display = "flex";
        pageDLC.style.flexWrap = "wrap";

        const input = document.createElement("input");

        input.type = "text";
        input.placeholder = "输入弹幕";

        input.style.width = "100%";
        input.style.padding = "10px";
        input.style.boxSizing = "border-box";

        pageDLC.appendChild(input);

        const button = document.createElement("button");
        button.textContent = "发送";
        button.style.padding = "10px";
        button.style.cursor = "pointer";
        button.style.width = "100%";
        pageDLC.appendChild(button);
        //
        const inputStyle = document.createElement("style");

        inputStyle.textContent = `input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button {display: none;}`;
        document.head.appendChild(inputStyle);

        const CDinput = document.createElement("input");
        CDinput.type = "number";
        CDinput.style.padding = "10px";
        CDinput.placeholder = "冷却秒数";
        CDinput.min = 0.01;
        CDinput.max = 100000;
        CDinput.style.minWidth = "0";

        const DLCbutton = document.createElement("button");
        DLCbutton.textContent = "独轮车启动";
        DLCbutton.style.padding = "10px";
        DLCbutton.style.cursor = "pointer";

        const row = document.createElement("div");
        row.style.display = "flex";
        row.style.width = "100%";

        CDinput.style.width = "30%";
        DLCbutton.style.width = "70%";


        row.append(CDinput, DLCbutton);

        pageDLC.appendChild(row);
        //
        button.onclick = () => {
            GM_setValue("SM2RR", { msg: input.value, time: Date.now() });
        };

        let timer = null;

        DLCbutton.onclick = () => {

            const value = CDinput.valueAsNumber;

            if (Number.isNaN(value)) {
                return;
            }

            if (timer) {
                // 已经在运行,不重复启动
                clearInterval(timer);
                timer = null;
                DLCbutton.textContent = "独轮车启动";
                DLCbutton.style.backgroundColor = "white";
                return;
            }


            DLCbutton.textContent = "独轮车启动中";
            DLCbutton.style.backgroundColor = "red";

            GM_setValue("SM2RR", { msg: input.value, time: Date.now() });

            timer = setInterval(() => {

                console.log("T发送");
                GM_setValue("SM2RR", { msg: input.value, time: Date.now() });

            }, CDinput.value*1000); // 每 1 秒发送一次

        };

        return pageDLC;
    }

    function createRandomDlcUI() {

        const page = document.createElement("div");
        page.style.display = "none";
        page.style.flexDirection = "column";
        page.style.gap = "10px";
        page.style.padding = "10px";

        function createRow() {

            const row = document.createElement("div");
            row.style.display = "flex";
            row.style.gap = "8px";
            row.style.alignItems = "center";

            const select = document.createElement("select");
            select.style.flex = "1";

            const addBtn = document.createElement("button");
            addBtn.textContent = "新增";

            const delBtn = document.createElement("button");
            delBtn.textContent = "删除当前";

            row.append(select, addBtn, delBtn);

            return {
                row,
                select,
                addBtn,
                delBtn
            };
        }

        // 第一行
        const row1 = createRow();
        row1.select.append(new Option("组1"));
        row1.select.append(new Option("组2"));
        row1.select.append(new Option("组3"));


        // 第二行
        const row2 = createRow();
        row2.select.append(new Option("随机弹幕1"));
        row2.select.append(new Option("随机弹幕2"))
        row2.select.append(new Option("随机弹幕3"))

        // 第三行
        const textarea = document.createElement("textarea");
        textarea.placeholder = "请输入内容...";
        textarea.style.width = "100%";
        textarea.style.height = "180px";
        textarea.style.resize = "vertical";
        textarea.style.boxSizing = "border-box";

        page.append(row1.row,row2.row,textarea);

        return page;
    }

    function sendMessageToRealChatRoom(msg) {

        const chatInput = document.querySelector(
            'yt-live-chat-text-input-field-renderer div[contenteditable]'
        );

        const sendButton = document.querySelector("#send-button button");

        if (!chatInput || !sendButton) {
            console.log("没找到聊天框");
            return;
        }

        chatInput.focus();

        chatInput.textContent = msg;

        chatInput.dispatchEvent(new InputEvent("input", {
            bubbles: true
        }));

        sendButton.click();
    }

    function showPage(pageShow,pageHide1,pageHide2) {

    pageShow.style.display = "block";
    pageHide1.style.display = "none";
    pageHide2.style.display = "none";


}

    function changeShowHide(pageShow,pageHide){
        pageShow.style.display = "flex";
        pageHide.style.display = "none";
    }


})();