Sleazy Fork is available in English.

Pornhub Pro-ish

Hides premium, sorts freemium, and hides watched videos

// ==UserScript==
// @name         Pornhub Pro-ish
// @namespace    https://www.reddit.com/user/Alpacinator
// @version      3.0.4
// @include      *://*.pornhub.com/*
// @grant        none
// @description  Hides premium, sorts freemium, and hides watched videos
// ==/UserScript==

(function() {
    'use strict';

    // Create a top bar element for buttons
    var topBar = document.createElement('div');
    topBar.style.position = 'fixed';
    topBar.style.top = '0';
    topBar.style.left = '0';
    topBar.style.width = '100%';
    topBar.style.backgroundColor = 'black';
    topBar.style.padding = '10px';
    topBar.style.zIndex = '9999'; // Ensure the bar appears on top of other elements
    topBar.style.display = 'flex';
    topBar.style.justifyContent = 'center'; // Center the buttons

    // Create a button to hide watched videos
    var hideButton = createButton('Hide watched videos', 'orange', toggleHideWatchedVideos);
    var hideWatchedVideosState = getToggleState('hideWatchedVideosState');
    toggleButtonColor(hideButton, hideWatchedVideosState);

    topBar.appendChild(hideButton);

    // Create a button to reorder freemium videos
    var reorderButton = createButton('Put Free Videos first', 'orange', toggleReorderItems);
    var reorderItemsState = getToggleState('reorderItemsState');
    toggleButtonColor(reorderButton, reorderItemsState);

    topBar.appendChild(reorderButton);

    // Create a button to manually reorder freemium videos
    var reorderManualButton = createButton('Put Free Videos first manually', 'black', sortPornhubElements);
    topBar.appendChild(reorderManualButton);

    // Create a button to sort videos by duration
    var sortByDurationButton = createButton('Sort by duration', 'black', sortVideosByDuration);
    topBar.appendChild(sortByDurationButton);

    // Create an input field to enter custom words to hide
    var customWordsInput = createTextInput('customTextInput', 'Words,to,hide,from,results', updateHiddenWords);
    var savedInputValue = localStorage.getItem('customInputValue');
    if (savedInputValue) {
        customWordsInput.value = savedInputValue; // Set the value of the input field
    }
  
    topBar.appendChild(customWordsInput);

    // Append the top bar to the body
    document.body.insertBefore(topBar, document.body.firstChild);

    // Add padding to the top of the body to create space for the top bar
    document.body.style.paddingTop = topBar.offsetHeight + 'px';

    // Initialize functions
    initializeHideWatchedVideos();
    initializeSortPornhubElements();

    // Call initializeSortPornhubElements periodically
    setInterval(function() {
        initializeSortPornhubElements();
    }, 2000);

    // Use MutationObserver to observe mutations
    const observer = new MutationObserver(function(mutations) {
        initializeHideWatchedVideos();
    });

    observer.observe(document, {
        childList: true,
        subtree: true
    });

    // Function to create a button with specified text, background color, and click event
    function createButton(text, bgColor, clickEvent) {
        var button = document.createElement('button');
        button.textContent = text;
        button.style.marginRight = '10px';
        button.style.padding = '5px 10px';
        button.style.backgroundColor = bgColor;
        button.style.color = 'white';
        button.addEventListener('click', clickEvent);
        return button;
    }

    // Function to create a text input field with specified attributes
    function createTextInput(id, placeholder, inputEvent) {
        var input = document.createElement('input');
        input.type = 'text';
        input.id = id;
        input.placeholder = placeholder;
        input.style.marginRight = '10px';
        input.addEventListener('input', inputEvent);
        return input;
    }

    // Function to toggle the color of a button based on a state
    function toggleButtonColor(button, state) {
        if (state) {
            button.style.backgroundColor = 'orange';
            button.style.color = 'black';
        } else {
            button.style.backgroundColor = 'grey';
            button.style.color = 'white';
        }
    }

    // Function to get the toggle state from localStorage
    function getToggleState(localStorageKey) {
        return localStorage.getItem(localStorageKey) === 'true';
    }

    // Function to toggle hide watched videos
    function toggleHideWatchedVideos() {
        hideWatchedVideosState = !hideWatchedVideosState; // Toggle the state
        localStorage.setItem('hideWatchedVideosState', hideWatchedVideosState);
        toggleButtonColor(hideButton, hideWatchedVideosState);
        initializeHideWatchedVideos();
    }

    // Function to initialize the hideWatchedVideos state on page load
    function initializeHideWatchedVideos() {
        var hideWatchedVideosEnabled = getToggleState('hideWatchedVideosState');
        manipulateVideoElements(hideWatchedVideosEnabled, customWordsInput.value.split(',').map(word => word.trim().toLowerCase()));
    }

    // Function to hide or show videos based on the hideWatchedVideosState state
    function manipulateVideoElements(hideWatchedVideosState, inputWords) {
        var liElements = document.querySelectorAll('li.pcVideoListItem');

        liElements.forEach(function (li) {
            var anchorElement = li.querySelector('a');
            var watchedText = li.querySelector('div.watchedVideoText');
            var watchedVideo = li.querySelector('div.watchedVideo');
            var priceSpan = li.querySelector('span.price');
            var premiumIcon = li.querySelector('li.premiumicon'); // New line to find <li> with class 'premiumicon'
            var liTextContent = li.textContent.toLowerCase();

            var shouldHideAnchorElement =
                anchorElement && anchorElement.getAttribute('href') === 'javascript:void(0)';
            var shouldHideByInputWords = inputWords.length > 0 && inputWords.some(word =>
                word.trim().length >= 3 && liTextContent.includes(word.trim())
            );
            var shouldHideByWatchedVideos = hideWatchedVideosState && (watchedText || watchedVideo);
            var shouldHideByPriceSpan = priceSpan;
            var shouldHideByPremiumIcon = premiumIcon; // New variable to check for the presence of premiumicon class

            li.style.display = (
                shouldHideAnchorElement ||
                shouldHideByInputWords ||
                shouldHideByWatchedVideos ||
                shouldHideByPriceSpan ||
                shouldHideByPremiumIcon
            ) ? 'none' : 'block';
        });
    }


    // Function to toggle reorder items
    function toggleReorderItems() {
        reorderItemsState = !reorderItemsState; // Toggle the state
        localStorage.setItem('reorderItemsState', reorderItemsState);
        toggleButtonColor(reorderButton, reorderItemsState);
        initializeSortPornhubElements();
    }

    // Function to initialize the reorderItems state on page load
    function initializeSortPornhubElements() {
        var reorderItemsEnabled = getToggleState('reorderItemsState');

        if (reorderItemsEnabled) {
            sortPornhubElements();
        }
    }

    // Function to sort <li> elements by duration in descending order
    function sortVideosByDuration() {
        function parseDuration(durationString) {
            var [hours, minutes] = durationString.split(':').map(Number);
            return hours * 60 + minutes;
        }

        function sortLiElementsByDurationDesc(ulId) {
            var listContainer = document.getElementById(ulId);

            if (!listContainer) {
                console.error(`List container with ID ${ulId} not found.`);
                return;
            }

            var liElements = Array.from(listContainer.querySelectorAll('li.pcVideoListItem'));

            if (liElements.length === 0) {
                console.warn(`No elements found in list container with ID ${ulId}. Skipping sorting.`);
                return;
            }

            liElements.sort(function (a, b) {
                var durationA = parseDuration(a.querySelector('.duration').textContent);
                var durationB = parseDuration(b.querySelector('.duration').textContent);
                return durationB - durationA;
            });

            listContainer.innerHTML = '';

            liElements.forEach(function (li) {
                listContainer.appendChild(li);
            });
        }

        sortLiElementsByDurationDesc('relatedVideosCenter');
        sortLiElementsByDurationDesc('singleFeedSection');
        sortLiElementsByDurationDesc('videoPlaylist');
        sortLiElementsByDurationDesc('recommendedVideos');
        sortLiElementsByDurationDesc('videoSearchResult');
        sortLiElementsByDurationDesc('videoCategory');
        sortLiElementsByDurationDesc('singleFeedSection');
    }


    // Function to update the list of custom words to hide
    function updateHiddenWords() {
        var inputValue = customWordsInput.value;
        localStorage.setItem('customInputValue', inputValue);

        var inputWords = inputValue.split(',').map(word => word.trim().toLowerCase());
        initializeHideWatchedVideos();
    }

    // Function to reorder freemium videos
    function sortPornhubElements() {
        var liElements = Array.from(document.querySelectorAll('li.pcVideoListItem'));
        var freePremiumVideoItems = [];
        var otherItems = [];

        liElements.forEach(function(li) {
            var childSpan = li.querySelector('span.phpFreeBlock');
            if (childSpan) {
                freePremiumVideoItems.push(li);
            } else {
                otherItems.push(li);
            }
        });

        var reorderedLiElements = freePremiumVideoItems.concat(otherItems);

        reorderedLiElements.forEach(function(li) {
            var parentElement = li.parentElement;
            parentElement.removeChild(li);
            parentElement.appendChild(li);
        });
    }
  
    // Hide elements with data-label="Related - Load More"
    const relatedLoadMoreElements = document.querySelectorAll('[data-label="related_load_more"]');
    relatedLoadMoreElements.forEach(element => {
        element.style.display = 'none';
    });

    // Hide elements with data-label="Recommended - Load More"
    const recommendedLoadMoreElements = document.querySelectorAll('[data-label="recommended_load_more"]');
    recommendedLoadMoreElements.forEach(element => {
        element.style.display = 'none';
    });

})();