您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
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 }); })();