Greasy Fork

Greasy Fork is available in English.

AttachHowOldtoUserinPosts

Show how old a user is in posts

当前为 2025-01-24 提交的版本,查看 最新版本

// ==UserScript==
// @name         AttachHowOldtoUserinPosts
// @namespace    https://jirehlov.com
// @version      1.9
// @description  Show how old a user is in posts
// @author       Jirehlov
// @match        https://bgm.tv/*
// @match        https://chii.in/*
// @match        https://bangumi.tv/*
// @grant        none
// @license      MIT
// ==/UserScript==
(function () {
	const delay = 4000;
	const jsonURL = "https://jirehlov.com/userages.json";
	const ageColors = [
		{
			threshold: 2,
			color: "#FFC966"
		},
		{
			threshold: 5,
			color: "#FFA500"
		},
		{
			threshold: 10,
			color: "#F09199"
		},
		{
			threshold: Infinity,
			color: "#FF0000"
		}
	];
	let usersToFetch = [];
	function calculateAge(birthDate) {
		const today = new Date();
		const dob = new Date(birthDate);
		let age = today.getFullYear() - dob.getFullYear();
		const monthDiff = today.getMonth() - dob.getMonth();
		if (monthDiff < 0 || monthDiff === 0 && today.getDate() < dob.getDate()) {
			age--;
		}
		return age;
	}
	function fetchUserAgesOnline() {
		const lastFetchTime = localStorage.getItem("userAges_lastFetchTime");
		const now = Date.now();
		if (!lastFetchTime || now - parseInt(lastFetchTime, 10) > 7 * 24 * 60 * 60 * 1000) {
			fetch(jsonURL).then(response => response.json()).then(data => {
				Object.keys(data).forEach(key => {
					localStorage.setItem(key, data[key]);
				});
				localStorage.setItem("userAgeslastFetchTime", now);
			}).catch(error => console.error("Failed to fetch user ages:", error));
		}
	}
	function displayUserAge(userId, registrationDate) {
		const userAnchor = $("strong a.l[href$='/user/" + userId + "']");
		if (userAnchor.length > 0 && userAnchor.next(".age-badge").length === 0) {
			const userAge = calculateAge(registrationDate);
			if (!isNaN(userAge)) {
				let badgeColor = ageColors.find(color => userAge <= color.threshold).color;
				const badge = `
                    <span class="age-badge" style="
                        background-color: ${ badgeColor };
                        font-size: 11px;
                        padding: 2px 5px;
                        color: #FFF;
                        border-radius: 100px;
                        line-height: 150%;
                        display: inline-block;
                    ">${ userAge }年</span>`;
				userAnchor.after($(badge));
			}
		}
	}
	function fetchAndStoreUserAge(userLink, delayTime) {
		setTimeout(() => {
			fetch(userLink).then(response => response.text()).then(data => {
				const parser = new DOMParser();
				const doc = parser.parseFromString(data, "text/html");
				let registrationDate = $(doc).find("ul.network_service li:first span.tip").text().replace(/加入/g, "").trim();
				if (registrationDate) {
					const userId = userLink.split("/").pop();
					localStorage.setItem("userAge_" + userId, registrationDate);
					displayUserAge(userId, registrationDate);
				}
			}).catch(error => console.error("Failed to fetch user age:", error));
		}, delayTime);
	}
	function importUserAges() {
		const input = document.createElement("input");
		input.type = "file";
		input.accept = "application/json";
		input.onchange = function (event) {
			const file = event.target.files[0];
			if (file) {
				const reader = new FileReader();
				reader.onload = function (e) {
					try {
						const userAges = JSON.parse(e.target.result);
						Object.keys(userAges).forEach(key => localStorage.setItem(key, userAges[key]));
						alert("导入成功");
					} catch (error) {
						alert("无效的JSON文件\uFF1A", error);
					}
				};
				reader.readAsText(file);
			}
		};
		input.click();
	}
	function exportUserAges() {
		const userAges = {};
		Object.keys(localStorage).forEach(key => {
			if (key.startsWith("userAge_")) {
				userAges[key] = localStorage.getItem(key);
			}
		});
		const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
		const entryCount = Object.keys(userAges).length;
		const filename = `userAges_${ timestamp }_${ entryCount }entries.json`;
		const blob = new Blob([JSON.stringify(userAges, null, 2)], { type: "application/json" });
		const url = URL.createObjectURL(blob);
		const a = document.createElement("a");
		a.href = url;
		a.download = filename;
		a.click();
		URL.revokeObjectURL(url);
	}
	fetchUserAgesOnline();
	const badgeUserPanel = document.querySelector("ul#badgeUserPanel");
	if (badgeUserPanel) {
		const importButton = document.createElement("a");
		importButton.href = "#";
		importButton.textContent = "导入用户生日数据";
		importButton.onclick = event => {
			event.preventDefault();
			importUserAges();
		};
		const exportButton = document.createElement("a");
		exportButton.href = "#";
		exportButton.textContent = "导出用户生日数据";
		exportButton.onclick = event => {
			event.preventDefault();
			exportUserAges();
		};
		const listItem = document.createElement("li");
		listItem.appendChild(importButton);
		badgeUserPanel.appendChild(listItem);
		const exportListItem = document.createElement("li");
		exportListItem.appendChild(exportButton);
		badgeUserPanel.appendChild(exportListItem);
	}
	$("strong a.l:not(.avatar)").each(function () {
		const userLink = $(this).attr("href");
		const userId = userLink.split("/").pop();
		const storedDate = localStorage.getItem("userAge_" + userId);
		if (storedDate) {
			displayUserAge(userId, storedDate);
		} else {
			usersToFetch.push(userLink);
		}
	});
	usersToFetch = [...new Set(usersToFetch)];
	usersToFetch.forEach((userLink, index) => {
		fetchAndStoreUserAge(userLink, index * delay);
	});
}());