NicoCommunity New Res Checkerが動かなくなっていたので

かってに直してみた。面倒なので、まとめて貼り付け。コミュニティページのAPI呼び出し処理と、APIのメソッド名、APIの戻り値に含まれるメソッド名が変更になっていたようだ。

// ==UserScript==
// @name           NicoCommunity New Res Checker
// @namespace      http://d.hatena.ne.jp/gifnksm/
// @description    Check Recent Writings
// @include        http://ch.nicovideo.jp/community*
// ==/UserScript==

if(new RegExp('^http://ch\\.nicovideo\\.jp/community/').test(location.href))
    return;


var com_data = eval(GM_getValue('com_data', '({})'));

function getData(com_id) {
    return com_data[com_id] || 0;
}
function setData(com_id, val) {
    com_data[com_id] = val;
    GM_setValue('com_data', com_data.toSource());
}

var show_new_res_only = GM_getValue('show_new_res_only', show_new_res_only);
var not_updated = [];
function showNode(node) { node.style.display = ''; }
function hideNode(node) { node.style.display = 'none'; }
function setNotUpdated(node) {
    not_updated.push(node);
    if(show_new_res_only)
        hideNode(node);
    else
        showNode(node);
}
function setVisiblity(visibility) {
    show_new_res_only = visibility;
    GM_setValue('show_new_res_only', show_new_res_only);
    if(show_new_res_only)
        not_updated.forEach(hideNode);
    else
        not_updated.forEach(showNode);
}


var getUniqueID = new function() {
    var i = 0;
    return function() {
        return i++;
    };
};

function getURL(url, callback) {
    GM_xmlhttpRequest({
        method: 'GET',
        headers: { 'User-Agent': 'Mozilla/5.0 Greasemonkey; NicoCommunity New Res Checker' },
        url: url,
        onload: function(response) {
            callback(response);
        },
        onerror: function() {
            callback(undefined);
        }
    });
}

const json_url_regexp = new RegExp('Nico\\.Community\\.BBS\\("bbs_summary", "bbs_template", "(co\\d+)", (\\d+), "([^"]+)"\\);')

function getResIdx(com_id, callback) {
    getURL('http://com.nicovideo.jp/community/' + com_id, function(response) {
        if(typeof(response) == 'undefined') {
            GM_log(com_id + ': "http://com.nicovideo.jp/community/' + com_id + '"の取得に失敗。');
            return callback(undefined);
        }
        var r = response.responseText.match(json_url_regexp);
        if(r == null) {
            GM_log(com_id + ': 最新書き込み取得APIのURL取得に失敗。');  
            return callback(undefined);
        }
        getURL('http://dic.nicovideo.jp/b/c/' + r[1] + '/api/res/l' + r[2] + '/NicoCommunityBBS_update_community_BBS/?hash_key=' + r[3], function(response) {
            if(typeof(response) == 'undefined') {
                GM_log(com_id + ': "' + r[1] + '"の取得に失敗。');
                return callback(undefined);
            }
            try {
                var array = eval(response.responseText.replace(/^NicoCommunityBBS_update_community_BBS/, ''), this);
                if(!(array instanceof Array) || array.length == 0)
                    callback(0);
                else
                    callback(array[array.length-1].n);
            } catch(e) {
                GM_log(com_id + ': JSONのパースに失敗。' + e.message);
                callback(undefined);
            }
        });
    });
}

function getResURL(com_id, res_idx) {
    var page_str = Math.floor((res_idx - 1) / 30) * 30 + 1;
    return 'http://dic.nicovideo.jp/b/c/' + com_id + '/' + page_str + '-#' + res_idx;
}

const id_prefix = 'GM_nicocom_new_res_check_';

function createResIdx(com_id, time, parent, callback) {
    var p = document.createElement('p');
    p.textContent = 'Waiting...';
    var p_id = id_prefix + 'p_' + getUniqueID();
    p.id = p_id;
    p.className = 'TXT12';
    parent.appendChild(p);
    setTimeout(function() {
        var p = document.getElementById(p_id);
        p.textContent = 'Loading...';
        getResIdx(com_id, function(res_idx) {
            try {
                if(typeof res_idx == 'undefined') {
                    GM_log(com_id + ': getResIdxからundefinedが返ってきた。');
                    p.textContent = '取得失敗';
                    return;
                }
                var first_idx = getData(com_id) + 1;
                var incr_num = res_idx - first_idx + 1;
                var container = p.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode;
                if(incr_num > 0) {
                    var bbs_link = document.createElement('a');
                    bbs_link.href = getResURL(com_id, first_idx);
                    bbs_link.textContent = '[読]';
                    
                    var finish_link = document.createElement('a');
                    finish_link.href = 'javascript: void();';
                    finish_link.textContent = '[了]';
                    finish_link.addEventListener('click', function() {
                        setData(com_id, res_idx);
                        p.textContent = res_idx;
                        setNotUpdated(container);
                    }, false);
                    
                    var f = document.createDocumentFragment();
                    f.appendChild(bbs_link);
                    f.appendChild(document.createTextNode(' '));
                    f.appendChild(finish_link);
                    
                    p.textContent = ' ' + res_idx + ' (' + incr_num + ')';
                    p.insertBefore(f, p.firstChild);
                }
                else {
                    p.textContent = res_idx;
                    setNotUpdated(container);
                }
            } finally {
                if(typeof callback == 'function')
                    callback();
            }
        });
    }, time);
}

var com_url_regex = new RegExp('(?:http://com\\.nicovideo\\.jp)?/community/(.+)$');

function checkUpdate(doc) {
    var callback = function() {};
    if (typeof window.AutoPagerize != 'undefined') {
        var ap = null;
        var callback = function() {
            if(ap != null)
                return ap.request();
            try {
                var _ap = eval('ap', window.AutoPagerize.addFilter);
                if(typeof _ap == 'object' && _ap != null && typeof _ap.request == 'function') {
                    ap = _ap;
                    return ap.request();
                }
            } catch(e) {
                ap = null;
            }
        };
    }
    var result = doc.evaluate(
        '//div[contains(concat(" ", @class, " "), " community_frm ")]/descendant::td[1]',
        doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
    if(result != null) {
        for(var i = 0, len = result.snapshotLength; i < len; i++)
        {
            var parent = result.snapshotItem(i);
            var com_link = parent.getElementsByTagName('a')[0];
            var r;
            if(com_link && (r = com_url_regex.exec(com_link.href)))
                createResIdx(r[1], i*500, parent, i == result.snapshotLength - 1? callback : undefined);
        }
    }
}

var button = document.createElement('button');
button.textContent = '更新チェック';

var update_checked = false;
button.addEventListener('click', function() {
    if(update_checked)
        return;
    update_checked = true;
    button.disabled = true;
    checkUpdate(document);
    if (typeof window.AutoPagerize != 'undefined')
        window.AutoPagerize.addDocumentFilter(checkUpdate);
}, false);

var h1 = document.getElementsByTagName('h1')[0];
h1.appendChild(document.createTextNode(' '));
h1.appendChild(button);

var label = document.createElement('label');
var input = document.createElement('input');
input.type = 'checkbox';
input.checked = show_new_res_only;
input.addEventListener('click', function() { setVisiblity(input.checked);},  false);
label.appendChild(input);
label.appendChild(document.createTextNode('新着のみ表示'));
h1.appendChild(document.createTextNode(' '));
h1.appendChild(label);