Snippets

Colin Cheng sf rate

Created by Colin Cheng last modified
// ==UserScript==
// @id             rate@segmentfault
// @name           segmentfault's user's question accepted rate
// @version        1.1
// @namespace      http://www.segmentfault.com/
// @author         zbinlin
// @description    显示用户的结贴率
// @updateURL      https://bitbucket.org/zbinlin/segmentfault-rate/raw/tip/rate@segmentfault.meta.js
// @include        http://www.segmentfault.com/q/*
// @include        http://segmentfault.com/q/*
// @include        https://www.segmentfault.com/q/*
// @include        https://segmentfault.com/q/*
// @run-at         document-end
// @grant          GM_xmlhttpRequest
// ==/UserScript==

"use strict";

var ajax = "function" === typeof GM_xmlhttpRequest ? GM_xmlhttpRequest : function GM_xmlhttpRequest(obj) {
    var xhr = new XMLHttpRequest();
    xhr.open(obj.method, obj.url, true);
    xhr.onload = (obj.onload || noop).bind(xhr);
    xhr.onerror = (obj.onerror || noop).bind(xhr);
    xhr.send(null);
    function noop() {}
};

let authorURL = (document.querySelector(".post-topheader .author > a") || {}).href;

let headers = new Headers();

let req = new Request(authorURL, {
    method: "GET",
    headers,
    mode: "same-origin"
});

let global = (() => this)();

let btn = document.createElement("a");
btn.textContent = "»查看结贴率«";
btn.style.cursor = "pointer";
btn.style.marginLeft = "1rem";
btn.addEventListener("click", function _(e) {
    btn.textContent = "查询中...";
    getAcceptedRate().then(questions => {
        questions = JSON.parse(questions);
        let rate = questions.filter(item => item).length / questions.length;
        let span = document.createElement("span");
        span.style.marginLeft = "1rem";
        span.style.color = "green";
        span.textContent = `[提问数:${questions.length} | 结贴率:${(rate * 100).toFixed(2)}%]`;
        btn.removeEventListener("click", _);
        btn.parentNode.replaceChild(span, btn);
        btn = undefined;
    }, err => {
        btn.textContent = "查询失败";
    });
});
let author = document.querySelector(".post-topheader .author");
author.appendChild(btn);
author = undefined;

function getAcceptedRate() {
    return fetch(req).then(res => res.text()).then(text => {
        let uid = (text.match(/data-id="(\d+)"[^>]*>\s*加关注/i) || [])[1];
        if (!uid) return Promise.reject("Can't find uid");
        return uid;
    }).then(uid => {
        let gen = getQuestions(`//api.segmentfault.com/user/${uid}/questions`);
        return co(gen);
    });
};

function coFetch(uri) {
    return new Promise((resolve, reject) => {
        ajax({
            method: "GET",
            url: uri,
            headers: {
                "Accept": "application/json,text/html;q=0.8,*/*;q=0.5",
                "Accept-Encoding": "gzip,deflate",
                "Connection": "key-alive",
                "User-Agent": "gm-httpengine v2.1.1"
            },
            onload: function (res) {
                let text = res.responseText;
                resolve({
                    json: function () {
                        try {
                            return JSON.parse(text);
                        } catch (ex) {}
                    }
                });
            },
            onerror: reject
        });
    });
}

function* getQuestions(url) {
    let page = 1;
    let questions = [];
    while (1) {
        let uri = url + "?page=" + page;
        let rst = yield coFetch(uri).then(res => res.json());
        let data = rst.data;
        if (data && Array.isArray(data.rows)) {
            questions.push(...data.rows.map(d => d.isAccepted));
        }
        if (data && data.page) {
            page = data.page.next;
        }
        if (!page) return JSON.stringify(questions);
    }
}

function co(gen) {
    return new Promise((resolve, reject) => {
        function next(val) {
            let ret = gen.next(val);
            if (ret.done) {
                resolve(ret.value);
            } else {
                ret.value.then(rst => {
                    next(rst);
                }).catch(err => {
                });
            }
        }
        next();
    });
}

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.