Old Reddit Karma & Account Age Display Next To Username

Shows karma counts and account age next to Reddit usernames

// ==UserScript==
// @name         Old Reddit Karma & Account Age Display Next To Username
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Shows karma counts and account age next to Reddit usernames
// @author       greenwenvy
// @match        https://www.reddit.com/*
// @match        https://old.reddit.com/*
// @grant        GM_xmlhttpRequest
// @connect      reddit.com
// @license      WTFPL
// ==/UserScript==

(function() {
    'use strict';

    // Determine if we're on old Reddit
    const isOldReddit = window.location.hostname === 'old.reddit.com';

    // Cache to avoid duplicate requests
    const userDataCache = {};

    // Function to get color based on account age
    function getAgeColor(createdDate) {
        const now = new Date();
        const created = new Date(createdDate * 1000);
        const ageInDays = Math.floor((now - created) / (1000 * 60 * 60 * 24));

        // Color scheme based on account age
        if (ageInDays < 30) {
            return '#e74c3c'; // Red for new accounts (< 1 month)
        } else if (ageInDays < 180) {
            return '#e67e22'; // Orange for newer accounts (< 6 months)
        } else if (ageInDays < 365) {
            return '#f1c40f'; // Yellow for accounts < 1 year
        } else if (ageInDays < 365 * 2) {
            return '#27ae60'; // Green for accounts 1-2 years
        } else if (ageInDays < 365 * 5) {
            return '#3498db'; // Blue for accounts 2-5 years
        } else {
            return '#8e44ad'; // Purple for accounts > 5 years
        }
    }

    // Function to format the date difference
    function formatTimeDifference(createdDate) {
        const now = new Date();
        const created = new Date(createdDate * 1000);
        const diffYears = now.getFullYear() - created.getFullYear();
        const diffMonths = now.getMonth() - created.getMonth();

        if (diffYears > 0) {
            return diffYears + (diffYears === 1 ? 'y' : 'y');
        } else if (diffMonths > 0) {
            return diffMonths + (diffMonths === 1 ? 'm' : 'm');
        } else {
            const diffDays = Math.floor((now - created) / (1000 * 60 * 60 * 24));
            return diffDays + (diffDays === 1 ? 'd' : 'd');
        }
    }

    // Function to fetch user data
    function fetchUserData(username) {
        // Return cached data if available
        if (userDataCache[username]) {
            return Promise.resolve(userDataCache[username]);
        }

        return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                method: 'GET',
                url: `https://www.reddit.com/user/${username}/about.json`,
                responseType: 'json',
                onload: function(response) {
                    if (response.status === 200 && response.response && response.response.data) {
                        // Cache the data
                        userDataCache[username] = response.response.data;
                        resolve(response.response.data);
                    } else {
                        reject('Failed to fetch user data');
                    }
                },
                onerror: function(error) {
                    reject(error);
                }
            });
        });
    }

    // Function to add karma display
    function addKarmaDisplay(userElement, userData) {
        // Check if we've already added karma info to this element
        if (userElement.getAttribute('data-karma-added') === 'true') {
            return;
        }

        // Create the karma display element
        const karmaDisplay = document.createElement('span');
        karmaDisplay.className = 'karma-display';
        karmaDisplay.style.fontSize = '10px'; // Smaller font
        karmaDisplay.style.color = '#888';
        karmaDisplay.style.marginLeft = '4px';

        // Format the karma numbers to be more compact
        const postKarma = userData.link_karma >= 1000 ?
            (userData.link_karma / 1000).toFixed(1) + 'k' :
            userData.link_karma;

        const commentKarma = userData.comment_karma >= 1000 ?
            (userData.comment_karma / 1000).toFixed(1) + 'k' :
            userData.comment_karma;

        // Create the display text without account age first
        let displayText = `(${postKarma}|${commentKarma})`;
        karmaDisplay.innerHTML = displayText;

        // Add account age for old Reddit with color
        if (isOldReddit) {
            const accountAge = formatTimeDifference(userData.created);
            const ageSpan = document.createElement('span');
            ageSpan.textContent = `|${accountAge}`;
            ageSpan.style.color = getAgeColor(userData.created);

            karmaDisplay.innerHTML = `(${postKarma}|${commentKarma}`;
            karmaDisplay.appendChild(ageSpan);
            karmaDisplay.innerHTML += ')';
        }

        // Insert the karma display after the username
        userElement.parentNode.insertBefore(karmaDisplay, userElement.nextSibling);

        // Mark this element as processed
        userElement.setAttribute('data-karma-added', 'true');
    }

    // Main function to find and process usernames
    function processUsernames() {
        // Selectors for both old and new Reddit
        const userSelectors = isOldReddit ?
            '.author:not([data-karma-added="true"]):not([data-karma-added="processing"])' :
            'a[href^="/user/"]:not([data-karma-added="true"]):not([data-karma-added="processing"]):not([href*="/comments/"]):not([href*="/submit/"])';

        const userElements = document.querySelectorAll(userSelectors);

        userElements.forEach(userElement => {
            // Skip already processed elements
            if (userElement.getAttribute('data-karma-added') === 'true' ||
                userElement.getAttribute('data-karma-added') === 'processing') {
                return;
            }

            const username = userElement.textContent.trim();

            // Skip if username is empty, contains special characters, or is a system user
            if (!username ||
                username.includes('[') ||
                username.includes('deleted') ||
                username === 'AutoModerator') {
                userElement.setAttribute('data-karma-added', 'true'); // Mark as processed
                return;
            }

            // Mark as being processed to prevent duplicate processing
            userElement.setAttribute('data-karma-added', 'processing');

            fetchUserData(username)
                .then(userData => {
                    addKarmaDisplay(userElement, userData);
                })
                .catch(error => {
                    console.error('Error fetching data for', username, error);
                    // Mark as processed even on error to prevent retries
                    userElement.setAttribute('data-karma-added', 'true');
                });
        });
    }

    // Throttle function to limit how often processUsernames runs
    function throttle(func, limit) {
        let inThrottle;
        return function() {
            const args = arguments;
            const context = this;
            if (!inThrottle) {
                func.apply(context, args);
                inThrottle = true;
                setTimeout(() => inThrottle = false, limit);
            }
        };
    }

    // Throttled version of processUsernames
    const throttledProcessUsernames = throttle(processUsernames, 1000);

    // Run on page load after a short delay
    setTimeout(processUsernames, 1000);

    // Set up a mutation observer to handle dynamically loaded content
    const observer = new MutationObserver(function(mutations) {
        // Check if any of the mutations might have added new user links
        let shouldProcess = false;
        for (let mutation of mutations) {
            if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                shouldProcess = true;
                break;
            }
        }

        if (shouldProcess) {
            throttledProcessUsernames();
        }
    });

    observer.observe(document.body, {
        childList: true,
        subtree: true
    });
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址