bilibili notify

自动监听bilibili直播推送信息,当所关注者开启直播时自动打开直播网页的javascript脚本。

当前为 2017-04-08 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name        bilibili notify
// @namespace   heroesm
// @include     http://live.bilibili.com/feed/getList/1
// @version     1.0.5.1
// @grant       none
// 
// @description 自动监听bilibili直播推送信息,当所关注者开启直播时自动打开直播网页的javascript脚本。
// ==/UserScript==
function main(){
    "use strict";
    
    var sAltAPI = 'http://api.live.bilibili.com/ajax/feed/list?pagesize=30&page=1';
    var running = true;
    var rProFilter, rConFilter;
    var rFilter = /./;
    var sMode = 'pro';
    var aTimer = [];
    var aAltRoomid = [];

    function prepare(){
        Document.prototype.$ = Document.prototype.querySelector;
        Element.prototype.$ = Element.prototype.querySelector;
        Document.prototype.$$ = Document.prototype.querySelectorAll;
        Element.prototype.$$ = Element.prototype.querySelectorAll;
    }
    function start(){
        var timer = setTimeout(function(){
            window.location.reload();
        }, 30000);
        aTimer.push(timer);
        document.$('#pause').style.display = 'unset';
        document.$('#start').style.display = 'none';
        return timer;
    }
    function stop(){
        var nTimer = aTimer.pop();
        while (nTimer){
            clearTimeout(nTimer);
            nTimer = aTimer.pop();
        }
        document.$('#pause').style.display = 'none';
        document.$('#start').style.display = 'unset';
    }
    function update(){
        try{
            var sCon = document.$('#con').value.trim();
            localStorage.bilinotify_con = sCon;
            rConFilter = new RegExp(sCon);
            var sPro = document.$('#pro').value.trim();
            localStorage.bilinotify_pro = sPro;
            rProFilter = new RegExp(sPro);
        } catch(e){console.log(e);}
        localStorage.bilinotify_mod = sMode = document.$('input[name=mode]:checked').value;
        if (sMode == 'pro'){
            rFilter = rProFilter;
        }
        else{
            rFilter = rConFilter; 
        }
    }
    function checkopen(item){
        var con = Boolean(sMode == 'con');
        if(con ^ rFilter.test(item.nickname)){
            window.open(item.link + '###', item.nickname);
        }
    }
    function build(){
        var style = document.createElement('style');
        style.id = 'bilinotify_css';
        style.innerHTML = [
            'input[type=text] {width: 50%;}'
        ].join('\n');
        document.head.appendChild(style);
        document.body.insertAdjacentHTML(
            'beforeend',
            [
                '<div class="con">',
                '    <input type="radio" name="mode" value="con">',
                '    <span>使用该正则表达式按昵称进行排除:</span>',
                '<input id="con" type="text" placeholder="不想看的A的昵称|B的昵称|C的昵称">',
                '</div>',
                '<div class="pro">',
                '    <input type="radio" name="mode" value="pro" checked>',
                '    <span>使用该正则表达式按昵称进行匹配:</span>',
                '    <input id="pro" type="text" placeholder="想看的A的昵称|B的昵称|C的昵称">',
                '</div>',
                '<div>',
                '    <button id="confirm">确认</button>',
                '    <button id="pause">暂停</button>',
                '    <button id="start">继续</button>',
                '</div>'
            ].join('\n')
        );
        if (localStorage.bilinotify_con){
            document.$('#con').value = localStorage.bilinotify_con;
        }
        if (localStorage.bilinotify_pro){
            document.$('#pro').value = localStorage.bilinotify_pro;
        }
        if (localStorage.bilinotify_mod){
            document.$('input[type=radio][value=' + localStorage.bilinotify_mod + ']').checked = true;
        }
        update();
        document.$('#confirm').onclick = update;
        document.$('#start').onclick = start;
        document.$('#pause').onclick = stop;
    }
    function run(){
        try{
            prepare();
        }catch(e){}
        var Obj = JSON.parse(document.body.childNodes[0].textContent.slice(1,-2));
        build();
        var Data = Obj.data;
        if(Obj.code == -101){
            document.body.insertAdjacentHTML('beforeend', '<br /><br />未登录');
            document.title = '未登录';
        }
        else if(Data.count>0) {
            document.title = "(!)有" + Data.count + "个直播";
            for(var x=0, item, sHTML; x<Data.count; x++){
                item = Data.list[x];
                if (aAltRoomid != null && aAltRoomid.indexOf(item.roomid) == -1){
                    document.body.insertAdjacentHTML(
                        'beforeend',
                        'erroneous response from server'
                    );
                    document.title = '信息错误';
                    throw 'erroneous response from server';
                }
                sHTML = ([
                    '<br />',
                    '<br />',
                    '<div style="clear:both;">',
                    '    <a style="float:left;" href="${item.link}"><img style="width:100px; height: 100px;" src="${item.face}"></img></a>',
                    '    <div style="float:left;">',
                    '        <span>${item.nickname}</span>',
                    '        <br>',
                    '        <a href="${item.link}">${item.roomname}</a>',
                    '    </div>',
                    '</div>'
                ].join('\n').replace(/\$\{([^\}]+)\}/g, function(sMatch, sP1){
                    return eval(sP1);
                }));
                document.body.insertAdjacentHTML(
                    'beforeend', 
                    sHTML
                );
                checkopen(item);
            }
        }
        else{
            document.body.insertAdjacentHTML('beforeend', '<br /><br />无直播');
            document.title = "无直播";
        }

        start();
        console.log('ended');
    }
    function handleAltList(sRes){
        var div = document.createElement('div');
        div.textContent = sRes;
        document.body.appendChild(div);
        var Obj = JSON.parse(sRes.slice(1,-2));
        if (Obj.code == 0){
            var aRooms = Obj.data.list;
            aRooms || (aRooms = []);
            for (var i=0; i<aRooms.length; i++){
                aAltRoomid.push(aRooms[i].roomid);
            }
        }
        else{
            aAltRoomid = null;
        }
    }
    function getAltList(callback){
        var xhr = new XMLHttpRequest();
        xhr.timeout = 5000;
        var sRes = '';
        xhr.ontimeout = xhr.onerror = function(e){
            console.log('timeout when getting alternative list');
            setTimeout(function(){
                window.location.reload();
            }, 5000);

        };
        xhr.onload = function(e){
            try{
                sRes = xhr.response;
                callback(sRes);
            }catch(e){
                console.log(e.toString());
                setTimeout(function(){
                    window.location.reload();
                }, 30000);
            }
        }
        xhr.withCredentials = true;
        xhr.open('get', sAltAPI)
        xhr.send();
    }
    
    getAltList(function(sRes){
        if (sRes){
            handleAltList(sRes);
        }
        run();
    });
    //run();
}

try{
    main();
}catch(e){
    console.log(e.toString());
    setTimeout(function(){
        window.location.reload();
    }, 30000);
}