Avoid losing a quote star

  • /*
     * @title Avoid losing a quote star
     * @description 人力検索などで引用スターに失敗するのを回避します。【注意】カラースターの対応ができてません (´・ω・`)
     * @include http://*
     * @include https://*
     * @license MIT License
     */
    /*
        http://q.hatena.ne.jp/1487227736#a1262105
    
        引用に失敗したっぽいときに
        - もう一度試す(最初の空振りしたスターは消す)
        - 引用は数値参照にする
    */
    (() => {
        const jsonp = (() => {
            var count = 0;
            return function(url, callback) {
                var callbackName = 'akuma3_jsonp'+count++;
                var script = document.createElement('script');
                script.src = url.replace(/[=]\?(&|$)/g, '='+callbackName+'$1');
                window[callbackName] = function(data) {
                    if (callback)
                        callback(data);
                    window[callbackName] = undefined;
                    try { delete window[callbackName]; } catch(e) {}
                    document.body.removeChild(script);
                };
                document.body.appendChild(script);
            };
        })();
    
        const StarRequest = function(url) {
            let a = url.split("?")
            this.__api__ = a[0]
            // parse parameter
            a[1].split("&").forEach(s => {
                let index = s.indexOf("=")
                if (index != -1) {
                    let k = s.slice(0, index), v = s.slice(index + 1)
                    this[k] = v
                } else {
                    // maybe timestamp
                    this.timestamp = s
                }
            })
            // method
            Object.assign(this, {
                to_parameter_string: function(p) {
                    let a = [
                        "uri=" + this.uri,
                        "rks=" + this.rks,
                        "timestamp=" + new Date().getTime(),
                    ]
                    for (k in p) {
                        a.push(k + "=" + p[k])
                    }
                    return a.join("&")
                },
                add_url: function(q) {
                    return this.__api__ + "?" + this.to_parameter_string({
                        title    : this.title  ,
                        quote    : (q ? q : this.quote)  ,
                        location : this.location  ,
                        callback : "?",
                    })
                },
                del_url: function(name) {
                    return "http://s.hatena.ne.jp/star.delete.json?" + this.to_parameter_string({
                        name : encodeURIComponent(name),
                    })
                },
                do_callback: function(json) {
                    let func = new Function("a", this.callback + "(a)")
                    func.call(null, json)
                },
                numeric_reference_quote: function() {
                    let s = decodeURIComponent(this.quote)
                    let o = "", i = 0
                    while (i < s.length) {
                        let code = s.codePointAt(i)
                        if (code > 128) {
                            o += "&#" + code + ";"
                            if (code > 0xffff) {    // for surrogate pair
                                i += 1
                            }
                        } else {
                            o += s.charAt(i)
                        }
                        i += 1
                    }
                    return encodeURIComponent(o)
                },
            })
        }
    
        const enhanced_add_star = (url) => {
            const req = new StarRequest(url)
            if (req.quote) {
                jsonp(req.add_url(), (data) => {
                    if (data.quote == "") { // has quote, but lose it !
    
                        // remove no quote star
                        jsonp(req.del_url(encodeURIComponent(data.name)))
    
                        // retry and use numeric character reference
                        jsonp(req.add_url(req.numeric_reference_quote()), (data) => {
                            console.log("a-kuma3: repair quote star. ", data)
                            req.do_callback(data)
                        })
    
                    } else {
                        req.do_callback(data)
                    }
                })
            } else {
                // no quote
                jsonp(url)
            }
        }
    
    
        const head = document.querySelector("head")
        const re_add_star = /s\.hatena\.ne\.jp\/star\.add\.json\?/
        head.appendChild = function(e) {
            if (e.tagName == 'SCRIPT' && re_add_star.test(e.src)) {
                enhanced_add_star(e.src)
            } else {
                // I believe e.nodeType == 1
                e.appendChild.call(this, e)
            }
        }
    
    })();
    
  • Permalink
    このページへの個別リンクです。
    RAW
    書かれたコードへの直接のリンクです。
    Packed
    文字列が圧縮された書かれたコードへのリンクです。
    Userscript
    Greasemonkey 等で利用する場合の .user.js へのリンクです。
    Loader
    @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
    Metadata
    コード中にコメントで @xxx と書かれたメタデータの JSON です。

History

  1. 2017/02/17 21:31:07 - 2017-02-17
  2. 2017/02/17 21:23:56 - 2017-02-17
  3. 2017/02/17 21:18:39 - 2017-02-17