coomer-optimizer

Improves coomer.party

Verzia zo dňa 28.08.2023. Pozri najnovšiu verziu.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==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';
                    }
                }
            }
        })
    }
})();