Greasy Fork

Greasy Fork is available in English.

bili指挥部(精准降落)

查找弹幕中的"指挥部"关键词,实现自动跳过片头

当前为 2020-06-28 提交的版本,查看 最新版本

// ==UserScript==
// @name         bili指挥部(精准降落)
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  查找弹幕中的"指挥部"关键词,实现自动跳过片头
// @author       kakasearch
// @match         *://www.bilibili.com/*
// @connect      comment.bilibili.com
// @run-at       document-end
// @grant        GM_xmlhttpRequest
// @license      MIT
// ==/UserScript==


function add_btn(){//添加开关,文字id bili_pass_text,开关danmu-pass-switch

    let otest
     let btn = ''


     let init_btn = setInterval(function(){
        otest = document.querySelector("div.bilibili-player-video-danmaku-root")
        if(otest){clearInterval(init_btn)//成功进入页面,开始执行功能
                  let checked = ''
                  if(setting.pass_op){//此p跳op
                      checked ='checked'}//默认开启
                  let otest = document.querySelector("div.bilibili-player-video-danmaku-root")
                  let node=document.querySelector("div.bilibili-player-video-danmaku-setting")
                  let nodestr = '<div class="bilibili-player-video-danmaku-switch bui bui-switch" ><input id="danmu-pass-switch" class="bui-switch-input" type="checkbox" '+checked+' ><label class="bui-switch-label"> <span class="bui-switch-name"></span> <span class="bui-switch-body">  <span class="bui-switch-dot"><span><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10"> <text  id = "danmu-pass-fill" fill="#00A1D6" stroke="#000" stroke-width="0" stroke-opacity="null" style="pointer-events: inherit; cursor: move;" x="0" y="7" font-size="8" text-anchor="start" xml:space="preserve" stroke-dasharray="none" font-weight="bold">op</text></svg></span>  </span> </span></label><span class="choose_danmaku" id="danmu-pass-text">关闭指挥部</span></div>'
                  let newnode=document.createRange().createContextualFragment(nodestr);
                  btn = document.querySelector("#danmu-pass-switch")
                  if(btn){info('重复添加')} //只添加一次
                  else{otest.insertBefore(newnode,node) ///添加开关节点
                  }


                  let fill = document.querySelector("#danmu-pass-fill")
                  let text = document.querySelector("#danmu-pass-text")

                      btn = document.querySelector("#danmu-pass-switch")
                      if(btn .checked){
                          //开
                          fill.setAttribute('fill','#00A1D6')
                          text.innerHTML='关闭指挥部'
                          setting.pass_op = 1//恢复默认
                      }else{
                          //off
                          fill.setAttribute('fill','#757575')
                          text.innerHTML='开启指挥部'
                          //本片所有剧集取消跳过
                          setting.pass_op = 0

                      }
                      btn.addEventListener('click',function(){
                      if(btn .checked){
                          //开
                          fill.setAttribute('fill','#00A1D6')
                          text.innerHTML='关闭指挥部'
                          setting.pass_op = 1//恢复默认
                      }else{
                          //off
                          fill.setAttribute('fill','#757575')
                          text.innerHTML='开启指挥部'
                          //本片所有剧集取消跳过
                          setting.pass_op = 0

                      }
                  });



                 }
    } )


    }



var setting={
    keyword:['感谢指挥部','精准降落','反手炸了指挥部','指挥部','指挥官','精准落地','感谢指路','精准'],
    badword:['呼叫','[吗呢怎么了??]'],//含有这些词的弹幕将被排除,例如 呼叫指挥部,指挥部呢?
    max_time:300,//单位秒,最大跳过时长,此时长之外的将视为不可信,0为不限制
    min_time:10,//单位秒,最小跳过时长,此时长之外的将视为不可信,0为不限制
    react_time:3,//弹幕发送的反应时间
    cid:'',//控制切p
    debug : 0,//开发模式
    pass_op : 1,//记录次剧集是否跳过
}
function info(){
    const arg = Array.from(arguments);
    arg.unshift(`color: white; background-color:#2274A5`);
    arg.unshift('%c bili指挥部:');
    console["info"].apply(console, arg);

}

function get_danmu(cid){//获取弹幕
    if(setting.debug){
        info('开始获取弹幕')
    }
    GM_xmlhttpRequest({
        method: 'GET',
        url: 'https://comment.bilibili.com/'+cid+'.xml',
        onload: function(xhr) {
            let found = 0
            let key_length = setting.keyword.length
            let bad_length = setting.badword.length
            if (xhr.status == 200) {
                let text = xhr.responseText.replace(/<\/d>/g,'\n')//弹幕中找指挥部
                for(let i=0;i <key_length;i++){
                    let pattern1 = new RegExp( "<d p=\"(\\d+\\.\\d+),.*?\">(.*?"+setting.keyword[i]+".*)", "gi");
                    let result = pattern1.exec(text)
                    if(result){

                        let danmu = result[2]//弹幕内容

                        for(let k=0;k<bad_length;k++){//检查是否有无效关键词  /////////////////////////////此处可优化至上步,一并匹配
                            let pattern2 = new RegExp( setting.badword[k], "gi");
                            if(pattern2.exec(danmu)){
                                if(setting.debug){info('无效弹幕',danmu)}
                                continue
                            }
                        }
                        //关键词是有效的
                        let target = Number(result[1])//指挥部所在时间
                        if((target<=setting.max_time&& target>=setting.min_time)||setting.max_time<=0){//指挥部可信
                            if(setting.debug){
                                info('找到指挥部,关键词',setting.keyword[i])

                            }

                            let video= document.querySelector("video")
                            video.currentTime = target-setting.react_time
                            video.play()
                            found = 1

                            info('已降落至指挥部,指示词:',setting.keyword[i])
                            break

                        }else{
                            if(setting.debug){
                                info('指挥部不可信,当前跳转时长范围:',setting.min_time,'--',setting.max_time)
                                info(result)
                            }

                        }

                    }
                }
                if(found==0){
                    info('未找到指挥部')
                    if(setting.debug){
                        info( text)
                    }
                }

            } else {
                info('获取弹幕失败')
            }
        }
    });
}
    function initfun(){
        //info('qie p')
        add_btn()//加开关

        let init = setInterval(function(){

            let cid = document.querySelector(" li.bilibili-player-video-btn-menu-list.bilibili-player-active.bilibili-player-blink").getAttribute('data-id')
            if(cid &&cid !=setting.cid){clearInterval(init) //成功进入页面,开始执行功能
                                        if(setting.pass_op){//开关控制是否要跳op
                                            setting.cid = cid//保证只允行1次
                                            get_danmu(cid)
                                        }else{info('off')}

                                       }
        },100)
        }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
(function() {
    initfun()
    let video= document.querySelector("#bofqi")
     let observer = new MutationObserver(initfun)
       observer.observe(video,{childList: true});//检测video变化,防止中途切p失效
    // Your code here...
})();