您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Improves coomer.party
// ==UserScript== // @name coomer-optimizer // @namespace https://coomer.su/ // @version 3.2 // @description Improves coomer.party // @match https://coomer.su/* // @grant GM_addStyle // @grant GM_setClipboard // @license MIT // @run-at document-end // @homepage https://greasyfork.org/en/scripts/468758-coomer-optimizer // ==/UserScript== (function () { 'use strict'; GM_addStyle('.card--dislike {border-color: hsl(0, 100%, 50%); border-style: solid; border-width: 2px; }'); GM_addStyle('.card--nevermet {border-color: hsl(120, 100%, 20%); border-style: solid; border-width: 2px; }'); /** * 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}`; } const getEl = function(_root_el, _tag, _class) { let _el; if (_root_el.tagName == _tag.toUpperCase() && _root_el.classList.contains(_class)) { _el = _root_el; } else if (_root_el.querySelector) { _el = _root_el.querySelector(`${_tag}.${_class}`); } return _el; } const rootOptimizer = function (_root) { 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/); //user page 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 ==================================================== //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`; } // dislike button 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'; }); let _summary_element, _parent_cssClass; if (userPageURLMatch) { _summary_element = document.createElement('div'); _summary_element.appendChild(summaryElement); _parent_cssClass = `${userPageCSSPrefix}__info` } else { _summary_element = summaryElement; _parent_cssClass = `${userPageCSSPrefix}__published` } //header let _pardiv = getEl(_root, 'div', _parent_cssClass); if (_pardiv) { _pardiv.appendChild(_summary_element); } //actions let _actdiv = getEl(_root, 'div', `${userPageCSSPrefix}__actions`); if (_actdiv) { _actdiv.appendChild(dislikeButton); } // footer optimization ====================================================================== // bottom header repeater let navMenu = getEl(_root, 'nav', 'post__nav-links'); let commentSection = getEl(_root, 'footer', 'post__footer'); if (navMenu && commentSection) { commentSection.appendChild(navMenu.cloneNode(true)); } // user post page if (userPostsPageURLMatch && (_root.querySelectorAll || _root.tagName == 'H2')) { // var headers = _root.getElementsByTagName('h2'); var headers = _root.tagName == 'H2' ? [_root] : _root.querySelectorAll('h2'); for (var i = 0; i < headers.length; i++) { if (headers[i].innerHTML == 'Downloads') { let copyDownloadsButton = document.createElement('button'); copyDownloadsButton.type = 'button'; copyDownloadsButton.className = `${userPageCSSPrefix}__favourite`; let textElement = document.createElement('span'); textElement.className = `${userPageCSSPrefix}__fav-text`; textElement.textContent = 'Copy'; copyDownloadsButton.appendChild(textElement); copyDownloadsButton.addEventListener('click', () => { var attachemnts = ''; var c = 0; document.querySelectorAll('a.post__attachment-link').forEach(l => { attachemnts += l.href + '\n'; c++; }); GM_setClipboard(attachemnts); console.log('copied (', c, ')'); }); headers[i].appendChild(copyDownloadsButton); } } } } else if (/* artist pages */ artistsPageURLMatch) { console.debug('Artist list page detected'); 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 += ' card--dislike'; } } else { c.className += ' card--nevermet'; } } if (_root.tagName == 'A' && _root.classList.contains('user-card')) { enrichUserCard(_root); } else if (_root.querySelectorAll) { _root.querySelectorAll('a.user-card').forEach(card => { enrichUserCard(card); }); } } else if (/*post list pages */ postsPageURLMatch) { console.debug('Post list page detected'); let enrichCard = function(card) { let summary = extractSummary(card.querySelector('a').href, true); console.debug(summary); if (summary) { card.className += ' co-parsed'; //if there is a summary if (summary.user) { console.debug('sum', summary); //replace attachment number with username card.querySelector('footer > div').textContent = `${summary.user} (${summary.visits})`; if (summary.disliked) { card.className += ' card--dislike'; } } else { card.querySelector('footer > div').textContent = summary; card.className += ' card--nevermet'; } } } if (_root.tagName == 'ARTICLE' && _root.classList.contains('post-card')) { enrichCard(_root); } else if (_root.querySelectorAll) { _root.querySelectorAll('article.post-card').forEach(card => { enrichCard(card); }) } } } // Create a MutationObserver to watch for changes in the DOM var observer = new MutationObserver(function (mutationsList, observer) { for (const mutation of mutationsList) { if (mutation.type === 'childList' && mutation.target && mutation.addedNodes.length > 0) { let _root = mutation.addedNodes[0]; rootOptimizer(_root); } } }); // Define the options for the observer const observerOptions = { childList: true, subtree: true }; // Start observing the document body for changes observer.observe(document.body, observerOptions); })();