Greasy Fork镜像 支持简体中文。

Old Reddit Karma & Account Age Display Next To Username

Shows karma counts and account age next to Reddit usernames

  1. // ==UserScript==
  2. // @name Old Reddit Karma & Account Age Display Next To Username
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.1
  5. // @description Shows karma counts and account age next to Reddit usernames
  6. // @author greenwenvy
  7. // @match https://www.reddit.com/*
  8. // @match https://old.reddit.com/*
  9. // @grant GM_xmlhttpRequest
  10. // @connect reddit.com
  11. // @license WTFPL
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. 'use strict';
  16.  
  17. // Determine if we're on old Reddit
  18. const isOldReddit = window.location.hostname === 'old.reddit.com';
  19.  
  20. // Cache to avoid duplicate requests
  21. const userDataCache = {};
  22.  
  23. // Function to get color based on account age
  24. function getAgeColor(createdDate) {
  25. const now = new Date();
  26. const created = new Date(createdDate * 1000);
  27. const ageInDays = Math.floor((now - created) / (1000 * 60 * 60 * 24));
  28.  
  29. // Color scheme based on account age
  30. if (ageInDays < 30) {
  31. return '#e74c3c'; // Red for new accounts (< 1 month)
  32. } else if (ageInDays < 180) {
  33. return '#e67e22'; // Orange for newer accounts (< 6 months)
  34. } else if (ageInDays < 365) {
  35. return '#f1c40f'; // Yellow for accounts < 1 year
  36. } else if (ageInDays < 365 * 2) {
  37. return '#27ae60'; // Green for accounts 1-2 years
  38. } else if (ageInDays < 365 * 5) {
  39. return '#3498db'; // Blue for accounts 2-5 years
  40. } else {
  41. return '#8e44ad'; // Purple for accounts > 5 years
  42. }
  43. }
  44.  
  45. // Function to format the date difference
  46. function formatTimeDifference(createdDate) {
  47. const now = new Date();
  48. const created = new Date(createdDate * 1000);
  49. const diffYears = now.getFullYear() - created.getFullYear();
  50. const diffMonths = now.getMonth() - created.getMonth();
  51.  
  52. if (diffYears > 0) {
  53. return diffYears + (diffYears === 1 ? 'y' : 'y');
  54. } else if (diffMonths > 0) {
  55. return diffMonths + (diffMonths === 1 ? 'm' : 'm');
  56. } else {
  57. const diffDays = Math.floor((now - created) / (1000 * 60 * 60 * 24));
  58. return diffDays + (diffDays === 1 ? 'd' : 'd');
  59. }
  60. }
  61.  
  62. // Function to fetch user data
  63. function fetchUserData(username) {
  64. // Return cached data if available
  65. if (userDataCache[username]) {
  66. return Promise.resolve(userDataCache[username]);
  67. }
  68.  
  69. return new Promise((resolve, reject) => {
  70. GM_xmlhttpRequest({
  71. method: 'GET',
  72. url: `https://www.reddit.com/user/${username}/about.json`,
  73. responseType: 'json',
  74. onload: function(response) {
  75. if (response.status === 200 && response.response && response.response.data) {
  76. // Cache the data
  77. userDataCache[username] = response.response.data;
  78. resolve(response.response.data);
  79. } else {
  80. reject('Failed to fetch user data');
  81. }
  82. },
  83. onerror: function(error) {
  84. reject(error);
  85. }
  86. });
  87. });
  88. }
  89.  
  90. // Function to add karma display
  91. function addKarmaDisplay(userElement, userData) {
  92. // Check if we've already added karma info to this element
  93. if (userElement.getAttribute('data-karma-added') === 'true') {
  94. return;
  95. }
  96.  
  97. // Create the karma display element
  98. const karmaDisplay = document.createElement('span');
  99. karmaDisplay.className = 'karma-display';
  100. karmaDisplay.style.fontSize = '10px'; // Smaller font
  101. karmaDisplay.style.color = '#888';
  102. karmaDisplay.style.marginLeft = '4px';
  103.  
  104. // Format the karma numbers to be more compact
  105. const postKarma = userData.link_karma >= 1000 ?
  106. (userData.link_karma / 1000).toFixed(1) + 'k' :
  107. userData.link_karma;
  108.  
  109. const commentKarma = userData.comment_karma >= 1000 ?
  110. (userData.comment_karma / 1000).toFixed(1) + 'k' :
  111. userData.comment_karma;
  112.  
  113. // Create the display text without account age first
  114. let displayText = `(${postKarma}|${commentKarma})`;
  115. karmaDisplay.innerHTML = displayText;
  116.  
  117. // Add account age for old Reddit with color
  118. if (isOldReddit) {
  119. const accountAge = formatTimeDifference(userData.created);
  120. const ageSpan = document.createElement('span');
  121. ageSpan.textContent = `|${accountAge}`;
  122. ageSpan.style.color = getAgeColor(userData.created);
  123.  
  124. karmaDisplay.innerHTML = `(${postKarma}|${commentKarma}`;
  125. karmaDisplay.appendChild(ageSpan);
  126. karmaDisplay.innerHTML += ')';
  127. }
  128.  
  129. // Insert the karma display after the username
  130. userElement.parentNode.insertBefore(karmaDisplay, userElement.nextSibling);
  131.  
  132. // Mark this element as processed
  133. userElement.setAttribute('data-karma-added', 'true');
  134. }
  135.  
  136. // Main function to find and process usernames
  137. function processUsernames() {
  138. // Selectors for both old and new Reddit
  139. const userSelectors = isOldReddit ?
  140. '.author:not([data-karma-added="true"]):not([data-karma-added="processing"])' :
  141. 'a[href^="/user/"]:not([data-karma-added="true"]):not([data-karma-added="processing"]):not([href*="/comments/"]):not([href*="/submit/"])';
  142.  
  143. const userElements = document.querySelectorAll(userSelectors);
  144.  
  145. userElements.forEach(userElement => {
  146. // Skip already processed elements
  147. if (userElement.getAttribute('data-karma-added') === 'true' ||
  148. userElement.getAttribute('data-karma-added') === 'processing') {
  149. return;
  150. }
  151.  
  152. const username = userElement.textContent.trim();
  153.  
  154. // Skip if username is empty, contains special characters, or is a system user
  155. if (!username ||
  156. username.includes('[') ||
  157. username.includes('deleted') ||
  158. username === 'AutoModerator') {
  159. userElement.setAttribute('data-karma-added', 'true'); // Mark as processed
  160. return;
  161. }
  162.  
  163. // Mark as being processed to prevent duplicate processing
  164. userElement.setAttribute('data-karma-added', 'processing');
  165.  
  166. fetchUserData(username)
  167. .then(userData => {
  168. addKarmaDisplay(userElement, userData);
  169. })
  170. .catch(error => {
  171. console.error('Error fetching data for', username, error);
  172. // Mark as processed even on error to prevent retries
  173. userElement.setAttribute('data-karma-added', 'true');
  174. });
  175. });
  176. }
  177.  
  178. // Throttle function to limit how often processUsernames runs
  179. function throttle(func, limit) {
  180. let inThrottle;
  181. return function() {
  182. const args = arguments;
  183. const context = this;
  184. if (!inThrottle) {
  185. func.apply(context, args);
  186. inThrottle = true;
  187. setTimeout(() => inThrottle = false, limit);
  188. }
  189. };
  190. }
  191.  
  192. // Throttled version of processUsernames
  193. const throttledProcessUsernames = throttle(processUsernames, 1000);
  194.  
  195. // Run on page load after a short delay
  196. setTimeout(processUsernames, 1000);
  197.  
  198. // Set up a mutation observer to handle dynamically loaded content
  199. const observer = new MutationObserver(function(mutations) {
  200. // Check if any of the mutations might have added new user links
  201. let shouldProcess = false;
  202. for (let mutation of mutations) {
  203. if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
  204. shouldProcess = true;
  205. break;
  206. }
  207. }
  208.  
  209. if (shouldProcess) {
  210. throttledProcessUsernames();
  211. }
  212. });
  213.  
  214. observer.observe(document.body, {
  215. childList: true,
  216. subtree: true
  217. });
  218. })();

QingJ © 2025

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