// ==UserScript==
// @name Greasyfork/Sleazyfork User Stats Display
// @description Displays total number of scripts and installs for users on Greasyfork/Sleazyfork.
// @icon https://greasyfork.org/vite/assets/blacklogo96-CxYTSM_T.png
// @version 1.0
// @author afkarxyz
// @namespace https://github.com/afkarxyz/misc-scripts/
// @supportURL https://github.com/afkarxyz/misc-scripts/issues
// @license MIT
// @match https://greasyfork.org/*/users/*
// @match https://greasyfork.org/users/*
// @match https://sleazyfork.org/*/users/*
// @match https://sleazyfork.org/users/*
// @grant none
// @downloadURL none
// ==/UserScript==
(function() {
'use strict';
// Wait for page to load
window.addEventListener('load', function() {
// Function to clean string and convert to number
const parseInstallCount = text => parseInt(text.replace(/,/g, '')) || 0;
// Select all spans and filter out the "Total installs" texts
const scripts = [...document.querySelectorAll('.script-list-total-installs span')]
.filter(element => !element.textContent.includes('Total installs'));
// Check if we found any scripts
if (scripts.length === 0) return;
// Calculate total installs
const totalInstalls = scripts.reduce((sum, element) =>
sum + parseInstallCount(element.textContent), 0);
// Create stats data
const statsData = {
scriptsCount: scripts.length,
totalInstalls: totalInstalls
};
// Create new element with same structure
const statsElement = document.createElement('section');
statsElement.id = 'user-stats';
// Get reference element
const userDiscussionsElement = document.getElementById('user-discussions');
if (!userDiscussionsElement) return;
// Copy specific styles instead of all computed styles
const stylesToCopy = [
'padding',
'border',
'borderRadius',
'backgroundColor',
'color',
'fontSize',
'fontFamily',
'lineHeight'
];
const computedStyle = window.getComputedStyle(userDiscussionsElement);
stylesToCopy.forEach(property => {
statsElement.style[property] = computedStyle.getPropertyValue(property);
});
// Create header with same style as original
const header = document.createElement('header');
const headerStyle = window.getComputedStyle(userDiscussionsElement.querySelector('header'));
header.style.padding = headerStyle.padding;
header.style.borderBottom = headerStyle.borderBottom;
const h3 = document.createElement('h3');
h3.textContent = 'Stats';
const originalH3Style = window.getComputedStyle(userDiscussionsElement.querySelector('h3'));
h3.style.margin = originalH3Style.margin;
h3.style.fontSize = originalH3Style.fontSize;
header.appendChild(h3);
// Create content section
const contentSection = document.createElement('section');
contentSection.className = 'text-content';
const originalContentStyle = window.getComputedStyle(userDiscussionsElement.querySelector('.text-content'));
contentSection.style.padding = originalContentStyle.padding;
// Create paragraph with bold numbers using strong elements
const p = document.createElement('p');
p.innerHTML = `This user has ${statsData.scriptsCount} script${statsData.scriptsCount !== 1 ? 's' : ''} with ${statsData.totalInstalls.toLocaleString()} total install${statsData.totalInstalls !== 1 ? 's' : ''}.`;
contentSection.appendChild(p);
// Assemble the elements
statsElement.appendChild(header);
statsElement.appendChild(contentSection);
// Insert the stats element after user-discussions
userDiscussionsElement.parentNode.insertBefore(statsElement, userDiscussionsElement.nextSibling);
});
})();