微博超级话题签到

在网页端自己的微博主页,把自己关注的超级话题一键全部签到。注意:只能在自己的个人主页签到。

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

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

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

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

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

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         微博超级话题签到
// @namespace    https://www.kindjeff.com/
// @version      2017.1.20
// @description  在网页端自己的微博主页,把自己关注的超级话题一键全部签到。注意:只能在自己的个人主页签到。
// @author       kindJeff
// @match        http://weibo.com/*
// @match        http://www.weibo.com/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    function get_topic_hash(response_text, page, user_id){
        // 从响应文本中解析出话题名称和 hash
        /* 参数: 
            response_text: 待解析的文本
            page: 当前页号,用来得到下一页的链接
            user_id: 用户ID
        */
        var result = {};
        var hash_start_index, name_start_index, name_end_index, name, hash;

        var name_index = response_text.indexOf('screen_name=');
        while(name_index != -1){
            // 循环得到 response_text 的话题名和 hash
            name_start_index = name_index + 12;
            name_end_index = response_text.indexOf('&', name_index);
            name = response_text.slice(name_start_index, name_end_index);
            hash = response_text.slice(name_index-56,name_index-56+38);
            result[name] = hash;
            name_index = response_text.indexOf('screen_name=', name_index + 100);
        }
        var next_index = response_text.indexOf('page next', name_end_index);
        if(next_index!==-1 && response_text.indexOf("Pl_Official_RelationInterested__95_page", next_index)!==-1){
            // 如果下一页链接可点,递归解析下一页的内容,并拼接到 result 里
            page += 1;
            var url = 'http://weibo.com/p/'+user_id+'/myfollow?pids=Pl_Official_RelationInterested__95&cfs=600&relate=interested&Pl_Official_RelationInterested__95_page='+page+'&ajaxpagelet=1&ajaxpagelet_v6=1&__ref=%2Fp%2F'+user_id+'%2Fmyfollow%3Frelate%3Dinterested%23place';
            var xhr_temp = new XMLHttpRequest();
            xhr_temp.open("GET", url, false);
            xhr_temp.send();
            var result_next_page = get_topic_hash(xhr_temp.responseText, page, user_id);
            Object.assign(result, result_next_page);
        }
        return result;
    }

    function sign(one_hash, name, retry_time){
        // 签到
        /* 参数:
            one_hash: 话题的 hash ,用来签到
            name: 话题的名称,用来交给 log_result 函数来显示
            retry_time: 重试的次数,用来决定是否终止
        */
        var xmlhttp_sign = new XMLHttpRequest();
        var s1 = "http://weibo.com/p/aj/general/button";
        var s2 = "?ajwvr=6&api=http://i.huati.weibo.com/aj/supercheckin&texta=%E7%AD%BE%E5%88%B0&textb=%E5%B7%B2%E7%AD%BE%E5%88%B0&status=0&id=";
        var url = s1 + s2 + one_hash + "&location=page_100808_super_index";
        xmlhttp_sign.open("GET", url, true);

        var re_sign = function(info){
            // 重新签到函数
            /* 参数:
                info: 出错信息,用来交给 log_error 函数输出
            */
            if(retry_time===undefined)
                retry_time = 0;
            retry_time += 1;

            if(retry_time<=5){
                log_error(name, '正在第 '+retry_time+' 次重试', info);
                setTimeout(sign, retry_time*retry_time*500, one_hash, name, retry_time);
            }else{
                log_error(name, '重试超过次数限制', info);
            }
        };

        // 弃用的部分,超时的处理
        // xmlhttp_sign.timeout = 7500;
        // xmlhttp_sign.ontimeout = function(){
        //     re_sign('签到超时');
        // };

        xmlhttp_sign.onreadystatechange = function(){
            if(xmlhttp_sign.readyState==4 && xmlhttp_sign.status==200){
                // 成功响应的时候
                var sign_result_str = xmlhttp_sign.responseText;
                var sign_result_obj = JSON.parse(sign_result_str);    // 把响应文本解析成 JSON
                var info = sign_result_obj['data']['alert_title'];    // 签到成功时,sign_result_obj.data.alert_title 是“今日签到 第X名”
                if(sign_result_obj['code']=='100000'){
                    // sign_result_obj.code 为 100000 时表示签到成功
                    log_result(name, info);
                }else{
                    re_sign(sign_result_obj['msg']);
                }
            }
        };

        xmlhttp_sign.onerror = function(){
            re_sign('签到出错');
        };

        xmlhttp_sign.send();
    }

    function log_error(name, error_result, error_info){
        console.log('出错: ', name, error_result, '出错信息: ', error_info, (new Date()));
    }

    function log_result(name, result){
        console.log(name, result);
    }

    function get_and_sign(retry_time){
        // 获得所有话题并且签到
        /* 参数:
            retry_time: xmlhttp_get_list 请求的重试次数
        */
        var user_id = document.getElementsByClassName('tab_link')[0].href.split('/')[4];    // 从“我的主页”按钮的链接获得用户 ID
        var xmlhttp_get_list = new XMLHttpRequest();

        xmlhttp_get_list.open('GET', 'http://weibo.com/p/'+user_id+'/myfollow?relate=interested&pids=plc_main&ajaxpagelet=1&ajaxpagelet_v6=1&__ref=%2Fp%2F'+user_id+'%2Fmyfollow%3Frelate%3Dinterested%23place', true);

        xmlhttp_get_list.onreadystatechange = function(){
            if(xmlhttp_get_list.readyState==4 && xmlhttp_get_list.status==200){
                // 成功响应的时候
                var topic_hash = get_topic_hash(xmlhttp_get_list.responseText, 1, user_id);    // 获得所有话题
                for(var name in topic_hash){
                    sign(topic_hash[name], name);
                }
                var s_b = document.getElementById("super_sign");
                s_b.innerText = "按F12看结果";
            }
        };

        xmlhttp_get_list.onerror = function(){
            // 出错重试
            if(retry_time===undefined)
                retry_time = 0;
            retry_time += 1;

            if(retry_time<=5){
                setTimeout(get_and_sign, retry_time*retry_time*500, retry_time);
            }else{
                console.log('爬取话题出错', (new Date()));
            }
        };

        xmlhttp_get_list.send();
    }


    function main(){
        // 插入“超级话题签到”按钮函数
        var sign_block = document.createElement('li');
        sign_block.setAttribute('id', 'super_sign');
        sign_block.innerText="超级话题签到";
        sign_block.onmouseover = function(){sign_block.style.color='red';};
        sign_block.onmouseout = function(){sign_block.style.color='black';};

        sign_block.onclick = function(){
            if(document.getElementsByClassName('tab_link').length!==0 && document.getElementsByClassName('tab_link')[0].innerText=="我的主页"){
                sign_block.innerText="正在签到...";
                get_and_sign();
                sign_block.onclick='';
                sign_block.onmouseover='';
                sign_block.onmouseout='';
            }else{
                window.location = '/profile';
            }
        };
        var the_con = document.getElementsByClassName('gn_nav_list')[0];
        var game = document.getElementsByClassName('gn_nav_list')[0].children[3];
        the_con.removeChild(game);
        the_con.appendChild(sign_block);
    }

    var init_func = function(){
        setTimeout(main, 3000);
    };

    if (document.readyState != 'loading'){
        init_func();
    }else{
        document.addEventListener('DOMContentLoaded', init_func);
    }
})();