Improves coomer.party
Ekde
// ==UserScript==
// @name coomer-optimizer
// @namespace https://coomer.party/
// @version 2.4
// @description Improves coomer.party
// @match https://coomer.party/*
// @grant GM_addStyle
// @license MIT
// @homepage https://greasyfork.org/en/scripts/468758-coomer-optimizer
// ==/UserScript==
(function() {
'use strict';
// Add the margin using CSS
GM_addStyle('div.card-list__items { margin-right: 500px; }');
/**
* 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);
}
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';
//replace attachment number with username
card.querySelector('footer > div').textContent = summary.user ? summary.user : summary;
//if there is a summary
if (summary.user) {
console.log('sum', summary);
if (summary.disliked) {
card.className += ' post-card--dislike';
}
}
}
})
}
})();