Greasy Fork

Greasy Fork is available in English.

知乎-我不感兴趣

隐藏掉知乎恼人的“你可能感兴趣”和“热门话题”推送

当前为 2018-03-17 提交的版本,查看 最新版本

// ==UserScript==
// @name         知乎-我不感兴趣
// @namespace
// @version      3.6
// @description  隐藏掉知乎恼人的“你可能感兴趣”和“热门话题”推送
// @author       MQ
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_notification
// @require      https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.18.2/babel.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.16.0/polyfill.js
// @match        www.zhihu.com
// @namespace http://greasyfork.icu/users/159603
// ==/UserScript==

/* jshint ignore:start */
var inline_src = (<><![CDATA[
    (async () => {
        'use strict';
        const MAX_FILTER_COUNT = 100; //最多主动刷新的条目数
        const USER_ID_KEY = "user-id";
        const USER_TOPICS_KEY = "user-topics";

        let GET = (url, headers) => {
            return new Promise((resolve, reject) => {
                let xhr = new XMLHttpRequest();
                xhr.open("GET", url, true);
                if (headers) {
                    Object.keys(headers).forEach((key) => { xhr.setRequestHeader(key, headers[key]); });
                }
                xhr.onload = (e) => {
                    if (xhr.readyState === 4) {
                        if (xhr.status === 200) {
                            resolve(xhr.responseText);
                        } else {
                            reject(xhr.statusText);
                        }
                    }
                };
                xhr.onerror = reject;
                xhr.send(null);
                return xhr.response;
            });
        };

        let getUserId = async () => {
            let raw = await GET("/api/v4/me");
            let data = JSON.parse(raw);
            return data.url_token;
        };

        let userId = GM_getValue(USER_ID_KEY, null);
        if (!userId) {
            userId = await getUserId();
            GM_setValue(USER_ID_KEY, userId);
        } else {
            setTimeout(async () => {
                let newValue = await getUserId();
                if (newValue != userId) {
                    userId = newValue;
                    GM_setValue(USER_ID_KEY, userId);
                }
            }, 1000);
        }

        let getUserTopics = async (uid) => {
            //以下部分获取用户关注话题
            let isEnd = true;
            let offset = 0;
            let topics = [];
            do {
                let raw = await GET(`/api/v4/members/${uid}/following-topic-contributions?offset=${offset}&limit=20`);
                let batch = JSON.parse(raw);
                isEnd = batch.paging.is_end;
                topics = topics.concat(batch.data.map(e => e.topic.name));
                offset += batch.data.length;
            } while(!isEnd);
            console.log("your followed topics", topics);
            return topics;
        };

        let followedTopics = GM_getValue(USER_TOPICS_KEY, null);
        if (!followedTopics) {
            followedTopics = await getUserTopics(userId);
            GM_setValue(USER_TOPICS_KEY, followedTopics);
        } else {
            setTimeout(async ()=> {
                let newValue = await getUserTopics(userId);
                if (newValue != followedTopics) {
                    followedTopics = newValue;
                    GM_setValue(USER_TOPICS_KEY, followedTopics);
                }
            }, 1000);
        }

        const mainFrame = document.querySelector(".TopstoryMain div");
        //全局中没被隐藏的卡片数
        let nonHiddenCards = 0;
        let allCards = 0;
        let fillNewCards = () => setTimeout(() => window.dispatchEvent(new Event("resize"))); //发送resize事件来补充新的内容
        //检查函数
        let checkCards = (cards) => {
            if (cards.length == 0) return;
            cards.forEach(e => {
                try{
                    if (e.hidden) return;
                    let feature = e.querySelector(".FeedSource-firstline");
                    let doHide = false;
                    if (feature.textContent.match(/你可能感兴趣|热门内容/)) {
                        doHide = true;
                        console.log(feature.textContent, "hide");
                    } else if (feature.textContent.match(/来自话题/)) {
                        var topicDivs = [...feature.querySelectorAll("div.Popover div")];
                        var topicNames = topicDivs.map(e=>e.textContent);
                        doHide = true;
                        for(let topicName of topicNames) {
                            if(followedTopics.includes(topicName)) {
                                doHide = false;
                                break;
                            }
                        }
                        console.log(topicNames, doHide ? "hide" : "not hide");
                    }
                    if (doHide) {
                        e.hidden = true;
                    } else {
                        nonHiddenCards++;
                    }
                    allCards++;
                } catch(x) {
                    console.log(x, e);
                }
            });
            if (nonHiddenCards < 8 && allCards < MAX_FILTER_COUNT) {
                console.log(`too few cards (${nonHiddenCards}/${allCards}) requesting for more...`);
                fillNewCards();
            } else if (nonHiddenCards < 8 && allCards >= MAX_FILTER_COUNT) {
                let option = {
                    text: `知乎-我不感兴趣 已为您过滤了 ${allCards-nonHiddenCards} 条推送,仍然没有足够的条目填满您的主页,您可以去喝杯茶,看看别的东西。`,
                    title: "主动刷新已停止",
                    onclick: console.log,
                    ondone: console.log
                };
                GM_notification(option, null);
                nonHiddenCards = 8;
            }
        };

        //注册钩子
        var ob = new MutationObserver((records) => {
            //console.log("mutation records: ", records);
            let addedCards = records.reduce((r, e) => r.concat([...e.addedNodes]), []);
            checkCards(addedCards);
        });
        var config = { childList: true };
        ob.observe(mainFrame, config);
        console.log("hooked");

        //进行首次检查,这里不DRY
        checkCards([...mainFrame.children]);
    })();
]]></>).toString();
var c = Babel.transform(inline_src, { presets: [ "es2015", "es2016", "es2017" ] });
console.log(c.code);
eval(c.code);
/* jshint ignore:end */