// ==UserScript== // @name B站弹幕+1工具 // @description 点击弹幕自动发送 + 快捷弹幕工具 // @namespace http://tampermonkey.net/ // @version 12.0.1 // @match https://live.bilibili.com/* // @grant none // ==/UserScript== if (!/^\/\d+/.test(location.pathname)) { console.log("⛔ 非直播间页面,不加载弹幕工具"); return; } (function () { 'use strict'; let config = { enabled: true, minInterval: 3000, delayMin: 500, delayMax: 1500, maxRepeat: 2, quickText: localStorage.getItem("quickText") || "哈哈哈,666,牛逼,冲冲冲" }; let lastSendTime = 0; // ===== 获取输入框 ===== function getInputBox() { return document.querySelector('textarea.chat-input') || document.querySelector('[contenteditable="true"]'); } // ===== 获取发送按钮 ===== function getSendBtn() { return [...document.querySelectorAll('button')] .find(btn => btn.innerText.trim() === '发送'); } // ===== 去用户名 ===== function cleanText(text) { const match = text.match(/^[^::]+[::]\s*(.*)$/); return match ? match[1] : text; } // ===== 发送(修复版)===== function sendDanmu(rawText) { const now = Date.now(); if (now - lastSendTime < config.minInterval) return; let text = cleanText(rawText); const delay = Math.random()*(config.delayMax-config.delayMin)+config.delayMin; setTimeout(() => { const input = getInputBox(); const btn = getSendBtn(); if (!input || !btn) { console.log("❌ 找不到输入框或按钮"); return; } // ===== 核心修复 ===== input.focus(); if (input.tagName === "TEXTAREA") { input.value = text; } else { input.innerText = text; } input.dispatchEvent(new InputEvent('input', { bubbles: true })); input.dispatchEvent(new Event('change', { bubbles: true })); btn.click(); lastSendTime = Date.now(); console.log("✅ 发送:", text); }, delay); } // ===== 点击弹幕发送 ===== function bindDanmuClick() { document.querySelectorAll('.chat-item').forEach(item=>{ if (item.dataset.binded) return; item.dataset.binded = 1; item.style.cursor = "pointer"; item.onclick = ()=>{ if (!config.enabled) return; sendDanmu(item.innerText.trim()); }; }); } // ===== 拖动 ===== function makeDraggable(el){ let down=false,ox,oy; el.onmousedown=e=>{down=true;ox=e.clientX-el.offsetLeft;oy=e.clientY-el.offsetTop;} document.onmousemove=e=>{ if(!down)return; el.style.left=e.clientX-ox+"px"; el.style.top=e.clientY-oy+"px"; el.style.right="auto"; } document.onmouseup=()=>down=false; } // ===== 候选词按钮 ===== function createQuickBtns(container){ container.innerHTML=""; config.quickText.split(',').map(s=>s.trim()).filter(Boolean).forEach(t=>{ const b=document.createElement("button"); b.innerText=t; b.style.cssText=` margin:3px;padding:4px 8px;border:none; border-radius:6px;background:#00a1d6;color:#fff;cursor:pointer; `; b.onclick=()=>sendDanmu(t); container.appendChild(b); }); } // ===== UI ===== function createPanel(){ const panel=document.createElement("div"); panel.style.cssText=` position:fixed;right:20px;top:200px;z-index:9999; background:rgba(30,30,30,0.95);color:#fff; padding:12px;border-radius:10px;font-size:12px; box-shadow:0 0 12px rgba(0,0,0,.6);width:230px; `; panel.innerHTML=`
弹幕工具

间隔
延迟 -
候选词:
`; document.body.appendChild(panel); makeDraggable(panel); const styleInput = (el)=>{ el.style.cssText=` width:60px;margin:2px; background:#222;color:#fff; border:1px solid #555;border-radius:4px; `; }; panel.querySelectorAll("input").forEach(styleInput); const textarea = panel.querySelector("#quickText"); textarea.style.cssText=` width:100%;height:50px;margin-top:3px; background:#222;color:#fff; border:1px solid #555;border-radius:4px; `; // 初始化 panel.querySelector("#interval").value=config.minInterval; panel.querySelector("#dmin").value=config.delayMin; panel.querySelector("#dmax").value=config.delayMax; textarea.value=config.quickText; const quickDiv=panel.querySelector("#quickBtns"); createQuickBtns(quickDiv); // ===== 持久化 ===== textarea.oninput=e=>{ config.quickText=e.target.value; localStorage.setItem("quickText", config.quickText); createQuickBtns(quickDiv); }; panel.querySelector("#enable").onchange=e=>config.enabled=e.target.checked; panel.querySelector("#interval").oninput=e=>config.minInterval=+e.target.value; panel.querySelector("#dmin").oninput=e=>config.delayMin=+e.target.value; panel.querySelector("#dmax").oninput=e=>config.delayMax=+e.target.value; } const observer=new MutationObserver(bindDanmuClick); window.addEventListener('load',()=>{ setTimeout(()=>{ createPanel(); bindDanmuClick(); observer.observe(document.body,{childList:true,subtree:true}); },3000); }); })();