您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
定时检测SC并保存,点击右上角下载sc存储为txt文件,点击列表显示sc,点击打call自动发送表情
// ==UserScript== // @name 【b站】【bilibili】直播间SC监控保存自动打call // @namespace http://alcedo.work // @version 3.1.1 // @description 定时检测SC并保存,点击右上角下载sc存储为txt文件,点击列表显示sc,点击打call自动发送表情 // @author alcedoM // @match https://live.bilibili.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=bilibili.com // @license AGPL-3.0 // @grant none // ==/UserScript== ( function() { 'use strict'; //修改页面 var navbar = document.getElementsByClassName("shortcuts-ctnr h-100 f-left")[0]; var body = document.getElementsByTagName("body")[0]; var toollist = document.createElement("div"); toollist.setAttribute("id","toollist"); toollist.setAttribute("data-v-00d38ec1",""); toollist.setAttribute("class","shortcut-item h-100 p-relative f-left pointer"); toollist.innerHTML = (` <div data-v-00d38ec1="" class="vertical-middle dp-table h-100"> <div class="dp-table-cell v-middle"> <div data-v-00d38ec1="" class="list-item p-relative"> <div data-v-00d38ec1="" class="text-label" style="color:#00aeec;" id="SC-script">SC脚本</div> </div> <div id="droptable" data-v-00d38ec1="" class="fanbox-panel-ctnr p-absolute over-hidden slot-component" style="display: none; top: 65px;" data-v-46cf49a2=""> <div style="width: 140px; height: 170px;" class=""> <div data-v-46cf49a2="" class="content-ctnr w-100 p-absolute p-zero" style=""> <div data-v-46cf49a2="" class="list-item a-move-in-left"> <span id="downloadsc" class="title">下载sc</span> </div> <div data-v-46cf49a2="" class=" list-item a-move-in-left"> <span id="cleardata" class="title">清除数据</span> </div> <div data-v-46cf49a2="" class=" list-item a-move-in-left"> <div class="switch-box" style=""> <div style="float: left;"> <span id="switch1Con">监控</span> </div> <div class="switch-container " style="float: right;"> <input type="checkbox" id="switch1" class="switch"> <label for="switch1" id="switchlable" onclick="test1()"></label> </div> </div> </div> <div data-v-46cf49a2="" class=" list-item a-move-in-left"> <div class="switch-box" style=""> <div style="float: left;"> <span id="switch1Con">打call</span> </div> <div class="switch-container " style="float: right;"> <input type="checkbox" id="switch2" class="switch"> <label for="switch2" id="dacall" onclick="test2()"></label> </div> </div> </div> <div data-v-46cf49a2="" class=" list-item a-move-in-left"> <div class="switch-box" style=""> <div style="float: left;"> <span id="switch1Con">sc列表</span> </div> <div class="switch-container " style="float: right;"> <input type="checkbox" id="switch3" class="switch"> <label for="switch3" id="showsclist" onclick="test3()"></label> </div> </div> </div> <style type="text/css"> .switch-container{ height: 24px; width:48px; margin-top:3px; } .switch{ display: none; } .switch-container label{ display: block; background-color: #eee; height: 100%; width: 100%; cursor: pointer; border-radius: 25px; position: relative; } .switch-container label:before { content: ''; display: block; border-radius: 25px; height: 100%; width: 24px; background-color: white; position: absolute; left: 0px; box-shadow: 1px 1px 1px 1px rgba(0, 0, 0, 0.08); -webkit-transition: all 0.5s ease; transition: all 0.5s ease; } #switch1:checked~label:before { left: 24px; } #switch1:checked~label { background-color: #00aeec; } #switch2:checked~label:before { left: 24px; } #switch2:checked~label { background-color: #00aeec; } #switch3:checked~label:before { left: 24px; } #switch3:checked~label { background-color: #00aeec; } </style> </div> </div> </div> </div> </div>`); navbar.insertBefore(toollist,navbar.children[3]); var sclist = document.createElement("div"); sclist.style.position = "absolute"; sclist.style.height = "400px"; sclist.style.width = "300px"; sclist.style.border = "1px solid #f1f2f3"; sclist.style.borderRadius = "10px"; sclist.style.backgroundColor = "white"; sclist.style.zIndex = "999"; sclist.style.right = "250px"; sclist.style.top = "65px"; sclist.style.padding = "5px"; sclist.style.display = "none"; sclist.innerHTML =(` <div id="my-sc-title" style="height:30px; line-height:30px; text-align:center">SC列表</div> <div style="overflow: hidden;"> <div id="my-sc-innerlist" style="height:370px;width: 316px;overflow-y: scroll;"></div> </div>` ); body.insertBefore(sclist,body.children[0]); var scInnerlist = document.getElementById("my-sc-innerlist"); var scTitle = document.getElementById("my-sc-title"); var rightpart = document.getElementById("right-part"); rightpart.style.cssText='max-width: 450px !important; min-width: 270px;'; // 初始化 var init_list = localStorage.init_list; var rawset = []; var is_monitor = false; var is_call = false; var sc_color_set = [["#edf5ff","#2a60b2"],["#dbfffd","#427d9e"],["#fff1c5","#e2b52b"],["#ffead2","#e09443"],["#ffe7e4","#e54d4d"],["#ffd8d8","#ab1a32"]]; var sc_count = 0; var url = window.location.href; // console.log(url); var match = url.match(/roomid=(\d+)/); if(match==null){ match = url.match(/live.bilibili.com\/(\d+)/); } var room_id = Number(match[1]); // console.log(room_id); var emoji_list = localStorage.getItem(room_id+"_emoji_list"); if (emoji_list==null){ emoji_list=[1,0,12]; }else{ emoji_list = JSON.parse(localStorage.getItem(room_id+"_emoji_list")); } var call_conut = 0; var call_limit_count = 0; if(init_list==null){ init_list = []; localStorage.setItem('init_list',JSON.stringify(init_list)); }else{ init_list = JSON.parse(localStorage.init_list); } if(init_list.indexOf(room_id) !== -1){ is_monitor = true; let chbx = document.getElementById('switch1'); chbx.checked = true; var sc_dataset = JSON.parse(localStorage.getItem("room_"+room_id)); if(sc_dataset==null){ console.log("error, can not found localStorage"); console.log("reload and try to reinit"); let index = init_list.indexOf(room_id); init_list.splice(index, 1); localStorage.setItem('init_list',JSON.stringify(init_list)); location.reload(); } var superchat = sc_dataset[0]; var ct = sc_dataset[1]; var timest = sc_dataset[2]; let time = new Date(); let timenow = time.toLocaleDateString(); if(timest!==timenow){ let flag = confirm(`检测到日期变更,是否清除本地数据,直播间:${room_id}`); if(flag){ clear_data(); } } //读取存储在本地的SC,并展示 for(let i = 0; i < superchat.length; i++){ add_sc_card(superchat[i][3],superchat[i][1],superchat[i][0],superchat[i][2]); } sc_count = superchat.length; scTitle.innerText=`SC列表(${sc_count})`; console.log('load success, 1'); } else{ } //定时中断 var timer = setInterval(function(){ //sc监视 if(is_monitor){ rawset = document.getElementsByClassName('superChat-card-detail'); if(rawset.length !== 0){ for (var i = 0; i < rawset.length; i++) { var index=ct.indexOf(rawset[i].dataset.ct); if(index == -1){ let time = new Date(); let money = rawset[i].children[0].innerHTML; let sc = [rawset[i].dataset.danmaku,rawset[i].dataset.uname,time.toLocaleTimeString(),money]; ct.push(rawset[i].dataset.ct); superchat.push(sc); console.log('sc:'+ i); //sc展示 add_sc_card(money,rawset[i].dataset.uname,rawset[i].dataset.danmaku,time.toLocaleTimeString()) sc_count = superchat.length; scTitle.innerText=`SC列表(${sc_count})`; } } } sc_dataset[0] = superchat; sc_dataset[1] = ct; localStorage.setItem("room_"+room_id,JSON.stringify(sc_dataset)); } //发送表情 if(is_call){ call_conut += 1; call_limit_count += 1; if(call_conut ==1 ){ let open_emotion = document.getElementsByClassName("emoticons-panel p-relative")[0]; open_emotion.click(); }else if(call_conut*3 >= emoji_list[2]){ call_conut = 0; let emotion_tab = document.getElementsByClassName("img-pane ps ps--theme_default")[emoji_list[0]]; let target_emoji = emotion_tab.children[0].children[emoji_list[1]]; target_emoji.click(); } //发送3分钟自动停止 if(call_limit_count>= 60){ call_limit_count = 0; document.getElementById('switch2').checked = false; is_call = 0; } } },3000) let downloadsc = document.getElementById('downloadsc'); let cleardata = document.getElementById('cleardata'); let dptb = document.getElementById('droptable'); //下拉菜单 toollist.onmouseover = function(){ listin(); } dptb.onmouseover = function(){ listin(); } toollist.onmouseout = function(){ listout(); } dptb.onmouseout = function(){ listout(); } function listin(){ let dptb = document.getElementById('droptable'); dptb.style.display="block"; } function listout(){ let dptb = document.getElementById('droptable'); dptb.style.display="none"; } //生成SC卡片 function add_sc_card(money,uname,danmaku,time){ let sc_color = []; console.log(money) let money_conut = parseInt(money.match(/\d+/)[0]); if(money_conut>=20000){ sc_color = sc_color_set[5]; }else if(money_conut>=10000){ sc_color = sc_color_set[4]; }else if(money_conut>=5000){ sc_color = sc_color_set[3]; }else if(money_conut>=1000){ sc_color = sc_color_set[2]; }else if(money_conut>=500){ sc_color = sc_color_set[1]; }else{ sc_color = sc_color_set[0]; } let scCard = document.createElement("div"); scCard.innerHTML=(` <div class="my-sc-card" style="height: auto;width:auto;border: 1px solid ${sc_color[1]}; border-radius: 6px; margin-bottom: 10px;"> <div class="sc-card-up" style="background-color: ${sc_color[0]};border-radius: 6px 6px 0 0;padding:5px 10px;height:30px; font-size: 16px; line-height: 30px;"> <div class="sc-card-right" style="float: left;">${uname}</div> <div class="sc-card-left" style="float: right;">${money}</div> </div> <div class="sc-card-down" style="min-height: 34px; background-color: ${sc_color[1]};color: white;padding:5px 10px;text-align: left;word-break: break-word;font-size: 14px;line-height:15px;border-radius: 0 0 6px 6px;"> ${time}:${danmaku} </div> </div>`) scInnerlist.appendChild(scCard); } //保存txt函数 downloadsc.onclick = function(){ let str = ""; let time = new Date(); let timedate = time.toLocaleDateString(); for (var i = 0; i < superchat.length; i++) { str += i +" "+ superchat[i].toString()+"\r\n" } var urlObject = window.URL || window.webkitURL || window; var export_blob = new Blob([str]); var save_link = document.createElementNS("http://www.w3.org/1999/xhtml", "a"); save_link.href = urlObject.createObjectURL(export_blob); save_link.download = `sc_${room_id}_${timest}.txt`; save_link.click(); } //点击清除数据 cleardata.onclick = function(){ let flag = confirm(`是否清除本地数据,直播间:${room_id}`); if(flag){ clear_data(); } } //清除本地数据 function clear_data(){ let time = new Date(); let timenow = time.toLocaleDateString(); ct =[]; superchat=[]; sc_dataset = [superchat,ct,timenow]; timest = timenow; localStorage.setItem("room_"+room_id,JSON.stringify(sc_dataset)); alert(`清除本地数据成功,直播间:${room_id}`); console.log(`clear success roomid:${room_id}`) } //开关的点击函数 //发送表情 var dacall = document.getElementById('dacall'); dacall.onclick = function(){ if (!document.getElementById('switch2').checked ) { let dacall_input = prompt(`请输入参数:第几个表情栏,第几个表情,发送间隔(尽可能为3的倍数且不宜太小)。示例:2,1,12表示每12s发送第2栏第1个表情“点赞”`,`${emoji_list[0]+1},${emoji_list[1]+1},${emoji_list[2]}`); if(dacall_input == null){ let ckbx = document.getElementById('switch2').checked; ckbx = false; }else{ // defaut_emoji = dacall_input; // console.log(defaut_emoji); let sp_arr = dacall_input.split(/[,, ]/); let fin_arr = []; let is_err = 0; if(sp_arr.length !== 3){ is_err = 1; alert(`输入参数数量错误,请重新输入`); }else{ for (let i = 0; i < sp_arr.length; i++) { if(isNaN(sp_arr[i])){ is_err = 1; alert(`请输入数字用逗号隔开`); break; }else if(parseInt(sp_arr[i]) <= 0){ is_err = 1; alert(`请输入正数`); break; }else{ fin_arr.push(parseInt(sp_arr[i])); } } // if(fin_arr[2] < 3){ // is_err = 1; // alert(`请输入大于3s的时间间隔`); // break; // } fin_arr[0] = fin_arr[0] - 1; fin_arr[1] = fin_arr[1] - 1; } if(is_err==0 && fin_arr!==[]){ emoji_list = fin_arr; localStorage.setItem(room_id+'_emoji_list',JSON.stringify(emoji_list)); call_limit_count = 0; is_call = 1; }else{ document.getElementById('switch2').checked = false; } } }else{ is_call = 0; } } //展示sc var showsclist = document.getElementById('showsclist'); showsclist.onclick = function(){ if (document.getElementById('switch3').checked ) { sclist.style.display = "none"; }else{ sclist.style.display = "block"; } } //切换监控开关 var slabel = document.getElementById('switchlable') slabel.onclick = function(){ if (!document.getElementById('switch1').checked ) { //开启 let flag = confirm(`是否监控本直播间SC:${room_id}`); if(flag){ let sc_dataset = localStorage.getItem("room_"+room_id); if(sc_dataset == null){ superchat = []; ct = []; init_list.push(room_id); let time = new Date(); let sc_dataset = [superchat,ct,time.toLocaleDateString()]; localStorage.setItem('init_list',JSON.stringify(init_list)); localStorage.setItem("room_"+room_id,JSON.stringify(sc_dataset)); }else{ init_list.push(room_id); localStorage.setItem('init_list',JSON.stringify(init_list)); } console.log('monitor open'); location.reload(); }else{ console.log('user deny, -1'); } }else{ let index = init_list.indexOf(room_id); init_list.splice(index, 1); is_monitor = false; localStorage.setItem('init_list',JSON.stringify(init_list)); console.log("close success"); } } } )();