知乎显示性别

为男女对立火上浇油[滑稽]

// ==UserScript==
// @name         知乎显示性别
// @namespace    https://skygate2012.github.io
// @version      0.3
// @description  为男女对立火上浇油[滑稽]
// @author       skygate2012
// @license      GPL-3.0-only
// @match        https://www.zhihu.com/*
// @match        https://zhuanlan.zhihu.com/*
// @icon         https://static.zhihu.com/heifetz/favicon.ico
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    class LRU {
        constructor(max) {
            this.max = max;
            this.cache = new Map();
        }

        get(key) {
            let item = this.cache.get(key);
            if (item) {
                // refresh key
                this.cache.delete(key);
                this.cache.set(key, item);
            }
            return item;
        }

        set(key, val) {
            // refresh key
            if (this.cache.has(key)) this.cache.delete(key);
            // evict oldest
            else if (this.cache.size == this.max) this.cache.delete(this.first());
            this.cache.set(key, val);
        }

        first() {
            return this.cache.keys().next().value;
        }
    }

    async function UserLink_display_user_gender(element) {
        if (element.textContent === "" || element.childElementCount > 0 || element.parentNode.querySelector(".gender-badge")) {
            return
        }
        const gender_badge = document.createElement("span");
        gender_badge.className = "gender-badge";
        element.parentNode.appendChild(gender_badge);
        const user_url = element.href;
        const username = user_url.substring(user_url.lastIndexOf('/') + 1);
        let user_info;
        let user_gender;
        if (typeof user_gender_cache.get(username) === "undefined") {
            user_gender_cache.set(username, null);
            try {
                //console.log("Fetching user info for", username);
                user_info = await (await fetch(`https://www.zhihu.com/api/v4/members/${username}`)).json();
                user_gender = user_info.gender;
                user_gender_cache.set(username, user_info.gender);
            } catch {
                //console.log("Failed to fetch user info for", username);
            }
        } else {
            while (user_gender_cache.get(username) === null) {
                await new Promise(r => setTimeout(r, 10));
            }
            user_gender = user_gender_cache.get(username);
        }
        let gender;
        switch (user_gender) {
            case 0:
                gender = "母";
                break;
            case 1:
                gender = "公";
                break;
            default:
                gender = "";
        }
        gender_badge.textContent = gender;
    }

    function Comment_UserLink_observer(mutationList) {
        mutationList.forEach(function(mutation) {
            mutation.target.querySelectorAll(".UserLink.AuthorInfo-name > .Popover > div > .UserLink-link, [class='UserLink'] > .Popover > div > .UserLink-link, .CommentItemV2-meta > .UserLink > .UserLink-link").forEach(UserLink_display_user_gender);
        });
    }

    let css =
        `
.gender-badge {
    color: #8590a6;
    margin-left: 0.3em;
}
    `
    let style = document.createElement('style');
    style.type = 'text/css';
    style.appendChild(document.createTextNode(css));
    document.head.appendChild(style);

    const user_gender_cache = new LRU(1000);
    const observer = new MutationObserver(Comment_UserLink_observer);
    observer.observe(document.body, {
        childList: true,
        subtree: true
    });
})();