// ==UserScript== // @name AttachHowOldtoUserinPosts // @namespace https://jirehlov.com // @version 1.5 // @description Show how old a user is in posts // @author Jirehlov // @match https://bgm.tv/*/topic/* // @match https://chii.in/*/topic/* // @match https://bangumi.tv/*/topic/* // @match https://bgm.tv/character/* // @match https://chii.in/character/* // @match https://bangumi.tv/character/* // @match https://bgm.tv/person/* // @match https://chii.in/person/* // @match https://bangumi.tv/person/* // @match https://bgm.tv/index/* // @match https://chii.in/index/* // @match https://bangumi.tv/index/* // @match https://bgm.tv/blog/* // @match https://chii.in/blog/* // @match https://bangumi.tv/blog/* // @match https://bgm.tv/ep/* // @match https://chii.in/ep/* // @match https://bangumi.tv/ep/* // @grant none // @license MIT // @downloadURL none // ==/UserScript== (function () { const delay = 2000; const ageColors = [ { threshold: 2, color: "#FFC966" }, { threshold: 5, color: "#FFA500" }, { threshold: 10, color: "#F09199" }, { threshold: Infinity, color: "#FF0000" } ]; let requestCount = 0; let usersToFetch = []; const sortedUserIds = Object.keys(localStorage).filter(key => key.startsWith("userAge_")).map(key => key.replace("userAge_", "")).filter(value => Number.isInteger(parseInt(value, 10))).map(value => parseInt(value, 10)).sort((a, b) => a - b); 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 findClosestMatchingDates(userId) { let lower = -1, upper = -1; for (let i = 0; i < sortedUserIds.length; i++) { if (sortedUserIds[i] < userId) { lower = sortedUserIds[i]; } if (sortedUserIds[i] > userId) { upper = sortedUserIds[i]; break; } } if (lower !== -1 && upper !== -1) { let lowerDate = localStorage.getItem("userAge_" + lower); let upperDate = localStorage.getItem("userAge_" + upper); if (lowerDate === upperDate) { return lowerDate; } } return null; } function fetchAndStoreUserAge(userLink, delayTime) { setTimeout(() => { $.ajax({ url: userLink, dataType: "html", success: function (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); } } }); }, delayTime); } 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 = ` ${ userAge }年`; userAnchor.after($(badge)); } } } $("strong a.l:not(.avatar)").each(function () { const userLink = $(this).attr("href"); const userId = userLink.split("/").pop(); let storedDate = localStorage.getItem("userAge_" + userId); if (!storedDate && !isNaN(userId)) { storedDate = findClosestMatchingDates(userId); if (storedDate) { console.log(`${ userId } ${ storedDate }`); } } if (storedDate) { localStorage.setItem("userAge_" + userId, storedDate); displayUserAge(userId, storedDate); } else { usersToFetch.push(userLink); } }); usersToFetch = [...new Set(usersToFetch)]; console.log("Users to fetch:", usersToFetch); usersToFetch.forEach((userLink, index) => { fetchAndStoreUserAge(userLink, index * delay); }); }());