Linux do Level Enhanced

Enhanced script to track progress towards next trust level on linux.do with added search functionality and adjusted posts read limit.

Fra 09.03.2024. Se den seneste versjonen.

// ==UserScript==
// @name         Linux do Level Enhanced
// @namespace    http://tampermonkey.net/
// @version      0.0.2
// @description  Enhanced script to track progress towards next trust level on linux.do with added search functionality and adjusted posts read limit.
// @author       Hua, Reno
// @match        https://linux.do/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=linux.do
// @grant        none
// @license      MIT
// ==/UserScript==

(async function() {
    'use strict';

    const ABOUT_DATA_URL = `https://linux.do/about.json`;
    const USER_DATA_URL_PREFIX = `https://linux.do/u/`;
    const USER_DATA_URL_SUFFIX = `/summary.json`;
    const FETCH_REQUEST_OPTIONS = {
        headers: {
            "Accept": "application/json",
            "User-Agent": "Mozilla/5.0"
        },
        method: "GET",
    };

    const levelRequirements = {
        0: { 'topics_entered': 5, 'posts_read_count': 30, 'time_read': 600 },
        1: { 'days_visited': 15, 'likes_given': 1, 'likes_received': 1, 'post_count': 3, 'topics_entered': 20, 'posts_read_count': 100, 'time_read': 3600 },
        2: { 'days_visited': 50, 'likes_given': 30, 'likes_received': 20, 'post_count': 10, 'posts_read_count': 0, 'topics_entered': 0 } // posts_read_count and topics_entered will be dynamically adjusted
    };

    const levelDescriptions = {
        0: "游客", 1: "基本用户", 2: "成员", 3: "活跃用户",
    };

    async function fetchAboutData() {
        try {
            const response = await fetch(ABOUT_DATA_URL, FETCH_REQUEST_OPTIONS);
            if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
            return await response.json();
        } catch (error) {
            console.error("Failed to fetch about data: ", error);
        }
    }

    async function fetchUserData(username) {
        try {
            const response = await fetch(`${USER_DATA_URL_PREFIX}${username}${USER_DATA_URL_SUFFIX}`, FETCH_REQUEST_OPTIONS);
            if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
            return await response.json();
        } catch (error) {
            console.error("Failed to fetch user data: ", error);
        }
    }

    function updatePopupContent(userSummary, user, status) {
        const popup = document.getElementById('linuxDoLevelPopupContent');
        if (popup && userSummary && user) {
            let content = `<strong>User Level:</strong> ${levelDescriptions[user.trust_level]}<br><strong>User Stats:</strong><br>`;

            const requirements = levelRequirements[user.trust_level];
            if (user.trust_level === 2) {
                requirements['posts_read_count'] = Math.min(Math.floor(status.posts_30_days / 4), 20000);
                requirements['topics_entered'] = Math.min(Math.floor(status.topics_30_days / 4), 500);
            }

            for (const stat in requirements) {
                const currentVal = userSummary[stat] || 0;
                const targetVal = requirements[stat];
                const color = currentVal >= targetVal ? "green" : "red";
                content += `${stat.replace(/_/g, ' ').replace('count', '')}: <span style="color: ${color};">${currentVal}`;
                if (targetVal !== undefined) {
                    content += ` / ${targetVal}`;
                }
                content += `</span><br>`;
            }

            popup.innerHTML = content;
        }
    }

    async function handleSearch() {
        const searchInput = document.getElementById('linuxDoUserSearch');
        const username = searchInput.value.trim();
        if (username) {
            const aboutData = await fetchAboutData();
            const userData = await fetchUserData(username);
            if (userData && aboutData) {
                const userSummary = userData.user_summary;
                const user = userData.users[0];
                const status = aboutData.about.stats;
                updatePopupContent(userSummary, user, status);
            }
        }
    }

    function createPopup() {
        const popup = document.createElement('div');
        popup.setAttribute('style', `position: fixed; bottom: 20px; right: 20px; width: 250px; height: auto; background-color: white; box-shadow: 0 0 10px rgba(0,0,0,0.5); padding: 15px; z-index: 10000; font-size: 14px; border-radius: 5px; overflow: auto;`);
        popup.id = 'linuxDoLevelPopup';

        const content = document.createElement('div');
        content.id = 'linuxDoLevelPopupContent';
        content.innerHTML = 'Loading user stats...';
        popup.appendChild(content);

        const searchBox = document.createElement('input');
        searchBox.setAttribute('type', 'text');
        searchBox.setAttribute('placeholder', 'Enter username...');
        searchBox.setAttribute('style', 'width: 100%; margin-top: 10px;');
        searchBox.id = 'linuxDoUserSearch';
        popup.appendChild(searchBox);

        const searchButton = document.createElement('button');
        searchButton.textContent = 'Search';
        searchButton.setAttribute('style', 'width: 100%; margin-top: 5px;');
        searchButton.addEventListener('click', handleSearch);
        popup.appendChild(searchButton);

        document.body.appendChild(popup);

        // 弹窗创建后30秒自动隐藏
        setTimeout(() => {
            popup.style.display = 'none';
        }, 30000); // 30秒后执行
    }

    createPopup();
})();