您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Improves coomer.party
当前为
// ==UserScript== // @name coomer-optimizer // @namespace https://coomer.party/ // @version 2.4.2 // @description Improves coomer.party // @match https://coomer.su/* // @grant GM_addStyle // @license MIT // @homepage https://greasyfork.org/en/scripts/468758-coomer-optimizer // ==/UserScript== (function() { 'use strict'; /** * Extract the summary object from the URL */ const extractSummary = function(url, orUser) { let m = url.match(/user\/([^\/]+)/); if (m) { let userKey = key(m[1]); let summary = JSON.parse(localStorage.getItem(userKey)); if (summary && !summary.user) { summary.user = m[1]; } // console.debug('URL: ', url, " --> key: ", userKey, " --> summary: ", summary); return summary ? summary : (orUser ? m[1] : summary); } else { // console.debug('URL: ', url, " --> no user"); return false; } } const key = function(_usr) { return `copt_${_usr}`; } let userPageURLMatch = window.location.pathname.match(/\/user\/([^/]+)$/); let userPostsPageURLMatch = window.location.pathname.match(/\/user\/([^/]+)\/post/); let artistsPageURLMatch = window.location.pathname.match(/\/artists/); let postsPageURLMatch = window.location.pathname.match(/\/posts/); if (userPageURLMatch || userPostsPageURLMatch) { let pageUser = false; let userPageCSSPrefix = false; if (userPageURLMatch) { pageUser = userPageURLMatch[1]; userPageCSSPrefix = 'user-header'; } else if (userPostsPageURLMatch) { pageUser = userPostsPageURLMatch[1]; userPageCSSPrefix = 'post'; } console.debug(`User page detected for ${pageUser}`); //adding styles GM_addStyle('span.user-header__dislike-icon::before { content: "\uD83D\uDC4E"; }'); let pageUserKey = key(pageUser); let today = new Date().toISOString().split('T')[0]; // Get the current date in ISO format //load or create the summary data for the user let summary = localStorage.getItem(pageUserKey); //If no summary data, we create it if (!summary) { summary = { user: pageUser, visits: 1, previousVisit: false, lastVisit: today, disliked: false }; } else { summary = JSON.parse(summary); } //Increment the number of visits if the page has been visited not today if (summary.lastVisit !== today) { summary.visits += 1; summary.previousVisit = summary.lastVisit; summary.lastVisit = today; if (!summary.user) { summary.user = pageUser; } } //Store the summary console.debug(`User ${pageUser}:`, summary); localStorage.setItem(pageUserKey, JSON.stringify(summary)); // header optimization ==================================================== let actionsDiv = document.querySelector(`div.${userPageCSSPrefix}__actions`); //summary text let summaryElement = document.createElement('span'); if (summary.previousVisit) { summaryElement.textContent = `- Visited ${summary.visits} times, last visit on ${summary.previousVisit}`; } else { summaryElement.textContent = `- First time visit`; } if (userPageURLMatch) { let d = document.createElement('div'); d.appendChild(summaryElement); document.querySelector(`div.${userPageCSSPrefix}__info`).appendChild(d); } else { document.querySelector(`div.${userPageCSSPrefix}__published`).appendChild(summaryElement); } let dislikeButton = document.createElement('button'); dislikeButton.type = 'button'; dislikeButton.className = `${userPageCSSPrefix}__favourite`; let iconElement = document.createElement('span'); iconElement.className = `${userPageCSSPrefix}__fav-icon` iconElement.textContent = summary.disliked ? '👍🏻' : '👎'; dislikeButton.appendChild(iconElement); let textElement = document.createElement('span'); textElement.className = `${userPageCSSPrefix}__fav-text`; textElement.textContent = summary.disliked ? 'Un-dislike' : 'Dislike'; dislikeButton.appendChild(textElement); dislikeButton.addEventListener('click', () => { summary.disliked = !summary.disliked; localStorage.setItem(pageUserKey, JSON.stringify(summary)); iconElement.textContent = summary.disliked ? '👍🏻' : '👎'; textElement.textContent = summary.disliked ? 'Un-dislike' : 'Dislike'; }); actionsDiv.appendChild(dislikeButton); // footer optimization ====================================================================== // bottom header repeater let navMenu = document.querySelector('nav.post__nav-links'); let commentSection = document.querySelector('footer.post__footer'); if (navMenu && commentSection) { commentSection.appendChild(navMenu.cloneNode(true)); } } // list pages if (artistsPageURLMatch) { console.debug('Artist list page detected'); // Styles GM_addStyle('.user-card--dislike {border-color: hsl(0deg 100% 50%); border-style: solid; border-width: 2px; }'); let enrichUserCard = function(c) { let summary = extractSummary(c.href); if (summary) { c.className += ' co-parsed'; let serviceLabel = c.querySelector('span.user-card__service'); let visitedLabel = serviceLabel.cloneNode(true); visitedLabel.textContent = `# ${summary.visits}`; visitedLabel.style.marginLeft = '4px'; visitedLabel.style.backgroundColor = 'rgb(240, 140, 207)'; serviceLabel.insertAdjacentElement('afterend', visitedLabel); if (summary.previousVisit) { let daysAfterLabel = visitedLabel.cloneNode(true); let daysFromLastVisit = Math.floor((new Date() - new Date(summary.previousVisit)) / (1000 * 60 * 60 * 24)); daysAfterLabel.textContent = `📅 ${daysFromLastVisit}` daysAfterLabel.title = `Last visit on ${summary.previousVisit}`; visitedLabel.insertAdjacentElement('afterend', daysAfterLabel); } if (summary.disliked) { c.className += ' user-card--dislike'; } } } // Callback function for the MutationObserver function mutationCallback(mutationsList, observer) { for (const mutation of mutationsList) { if (mutation.type === 'childList') { // Process newly added user cards mutation.addedNodes.forEach(node => { if (node.tagName === 'A' && node.classList.contains('user-card') && !node.classList.contains('co-parsed')) { enrichUserCard(node); } }); } } } // Create a MutationObserver to watch for changes in the DOM const observer = new MutationObserver(mutationCallback); // Define the options for the observer const observerOptions = { childList: true, subtree: true }; // Start observing the document body for changes observer.observe(document.body, observerOptions); } // post list pages if (postsPageURLMatch) { console.debug('Post list page detected'); // Styles GM_addStyle('.post-card--dislike {border-color: hsl(0deg 100% 50%); border-style: solid; border-width: 2px; }'); document.querySelectorAll('article.post-card').forEach(card => { let summary = extractSummary(card.querySelector('a').href, true); console.log(summary); if (summary) { card.className += ' co-parsed'; //if there is a summary if (summary.user) { console.log('sum', summary); //replace attachment number with username card.querySelector('footer > div').textContent = `${summary.user} (${summary.visits})`; if (summary.disliked) { card.className += ' post-card--dislike'; } } else { card.querySelector('footer > div').textContent = summary; } } }) } })();