Camwhores.tv Utilities Mod

Info preview, removal of lock from friends' vidoes, restored upload button, and more.

As of 24.05.2024. See ბოლო ვერსია.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Camwhores.tv Utilities Mod
// @namespace    https://sleazyfork.org/users/1281730-vipprograms
// @version      1.6.0
// @description  Info preview, removal of lock from friends' vidoes, restored upload button, and more.
// @author       vipprograms
// @match        https://www.camwhores.tv/*
// @grant        GM_xmlhttpRequest
// @grant        GM.getValue
// @grant        GM_getValue
// @grant        GM.setValue
// @grant        GM_setValue
// @grant        GM_registerMenuCommand
// @grant        GM.registerMenuCommand
// @grant        window.close
// @icon         data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAMUExURQAAAP8ANwwA/////7gbQJkAAAABdFJOUwBA5thmAAAAAWJLR0QDEQxM8gAAAAd0SU1FB+gDHhIuCjXV/h8AAAA4SURBVAjXY2ANDQ1gEA0NDWEIYWBgZAhgAAIUghEiC1YHBhpMDRpIhBbXghUMXKtWLWBgWqHVAACjlwz/pN0YPwAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyNC0wMy0zMFQxODo0NjowOSswMDowME+iXNIAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjQtMDMtMzBUMTg6NDY6MDkrMDA6MDA+/+RuAAAAKHRFWHRkYXRlOnRpbWVzdGFtcAAyMDI0LTAzLTMwVDE4OjQ2OjEwKzAwOjAwMNiA/AAAAABJRU5ErkJggg==
// @require      https://code.jquery.com/jquery-3.7.1.slim.min.js
// ==/UserScript==

(function() {
    'use strict';

    var _GM_registerMenuCommand, options;
    const refreshMessagesTimer = 2500;

    function isArrayEmpty(arr) {
        return arr.length === 0;
    }
    function retrieveValueFromStorage(key) {
        if (typeof GM_setValue === "function") {
            return GM_getValue(key, false); // Default value set to false for boolean
        }
        else if (typeof GM === "object" && typeof GM.getValue === "function" && typeof GM.setValue === "function") {
            return GM.getValue(key, false).then(function(value) {
                return value;
            });
        }
        else {
            console.error("Unsupported userscript manager.");
            return undefined;
        }
    }

    function saveValue(key, array) {
        GM.setValue(key, array).then(function() {
            console.log("Array saved successfully.");
        }).catch(function(error) {
            console.error("Error saving array:", error);
        });
    }

    if (typeof GM_registerMenuCommand !== 'undefined') {
        _GM_registerMenuCommand = GM_registerMenuCommand;
    } else if (typeof GM !== 'undefined' && typeof GM.registerMenuCommand !== 'undefined') {
        _GM_registerMenuCommand = GM.registerMenuCommand;
    } else {
        _GM_registerMenuCommand = (s, f) => { debug(s); debug(f); };
    }

    function toggleChange(options, optionName, defaultValue = false){
        var updatedOptions;
        var currentState = options[optionName] !== undefined ? options[optionName] : defaultValue;
        _GM_registerMenuCommand((currentState ? "Disable " : "Enable ") + optionName, () => {
            currentState = !currentState;
            updatedOptions[optionName] = currentState;
            saveValue("options", updatedOptions);

            setTimeout(() => {
                location.reload();
            }, 500);
        });

        updatedOptions = retrieveValueFromStorage("options") || {}; // Ensure options exist
        if (updatedOptions[optionName] === undefined) {
            updatedOptions[optionName] = defaultValue;
            saveValue("options", updatedOptions);
        }
    }

    function createForm(array_name, delimitedString){
        return new Promise((resolve, reject) => {
            var form = document.createElement('form');
            form.classList.add('form-container');

            var textBox = document.createElement('textarea');
            textBox.classList.add('textarea-input');
            textBox.setAttribute('autofocus', 'autofocus');


            var buttonsLine = document.createElement('div');
            buttonsLine.classList.add('buttons-line');

            var submitButton = document.createElement('button');
            submitButton.type = 'submit';
            submitButton.textContent = 'Submit';
            submitButton.classList.add('submit-button');

            var cancelButton = document.createElement('button');
            cancelButton.type = 'button';
            cancelButton.textContent = 'Cancel';
            cancelButton.classList.add('cancel-button');
            cancelButton.addEventListener('click', function() {
                document.body.removeChild(form);
                reject('Form cancelled');
            });

            window.addEventListener('click', function(event) {
                if (document.body.contains(form) && !form.contains(event.target)) {
                    document.body.removeChild(form);
                    reject('Form cancelled');
                }
            });

            textBox.value = delimitedString;

            form.appendChild(textBox);
            form.appendChild(buttonsLine);
            buttonsLine.appendChild(cancelButton);
            buttonsLine.appendChild(submitButton);

            document.body.appendChild(form);

            form.addEventListener('submit', function(event){
                event.preventDefault();
                var inputValue = textBox.value.split('\n').map(line => line.trim()).filter(line => line !== '');
                document.body.removeChild(form);
                resolve(inputValue);
            });
        });
    }


    function optionsArrayEditor(array_name, optionsKeyLegible){

        _GM_registerMenuCommand("Change " + optionsKeyLegible[array_name], () => {
            var originalArray = retrieveValueFromStorage(array_name);
            var delimitedString = originalArray.join("\n");

            createForm(array_name, delimitedString).then(lines => {
                saveValue(array_name, lines);
            });

        });
    }

function optionsStringEditor(string_name, optionsKeyLegible) {
    _GM_registerMenuCommand("Change " + optionsKeyLegible[string_name], () => {
        var originalString = retrieveValueFromStorage(string_name);
        createForm(string_name, originalString).then(lines => {
            // Convert array 'lines' to a string by joining values with '\n'
            let stringifiedLines = lines.join('\n');
            saveValue(string_name, stringifiedLines);
        });

    });
}

    const auto_replies_default = ["Next time you send me a request with 0 videos, I'll block you",
                                  "Very nice videos",
                                  "Why? What's wrong?",
                                  "Sorry, I don't like your videos",
                                  "You don't have any videos"];
    const highlight_keywords_default = ['joi', 'cei', 'fuck', "cumshot"];
    const friend_request_text_default = "Hi! I'm interested in this video:";

    var auto_replies = retrieveValueFromStorage("auto_replies");
    var highlight_keywords = retrieveValueFromStorage("highlight_keywords");
    var friend_request_text = retrieveValueFromStorage("friend_request_text");

    if (!auto_replies) {
        auto_replies = auto_replies_default;
        saveValue("auto_replies", auto_replies_default);
    }
    if (!highlight_keywords) {
        highlight_keywords = highlight_keywords_default;
        saveValue("highlight_keywords", highlight_keywords_default);
    }
    if (!friend_request_text) {
        friend_request_text = friend_request_text_default;
        saveValue("friend_request_text", friend_request_text_default);
    }

    var optionsKeyLegible = {
      auto_replies: "template replies",
      highlight_keywords: "highlight keywords",
      friend_request_text: "friend requests text"
    }
    optionsArrayEditor("auto_replies", optionsKeyLegible)
    optionsArrayEditor("highlight_keywords", optionsKeyLegible)
    optionsStringEditor("friend_request_text", optionsKeyLegible)


    // BOOL OPTIONS
    options = retrieveValueFromStorage("options")

    toggleChange(options, "alternative thumbnails", true)
    var altThumbs = retrieveValueFromStorage("options")["alternative thumbnails"];

    toggleChange(options, "message page auto refresh", true)
    var refreshMessagePage = retrieveValueFromStorage("options")["auto refresh message page"];

    toggleChange(options, "upload button restore", true)
    var restoreUploadButton = retrieveValueFromStorage("options")["restore upload button"];



    const style = document.createElement('style');
    style.textContent = `
      a.button{
      color:#4e4e4e !important;
      }
      ul > li.next,
      ul > li.prev {
        display: list-item !important;
      }
       .item:hover > a > div.img > .friends-tag,
       .item:hover > a > div.img > .videos-tag{
        background-color:#1a1a1a !important;
      }
      .button{
        color: rgb(183, 176, 167);
        text-align: center;
        border: 1px solid transparent;
        font-size: 14px;
        padding: 5px 10px;
        cursor: pointer;
        background: linear-gradient(to bottom, #ffffff 0%, #cccccc 100%);
        border-radius: 3px;
        display: inline-block;
        margin: 0 .3rem .3rem 0;
        color: dimgrey;
      }
      .button:hover{
        color: #f56c08 !important;
        border: 1px solid transparent;
        background: #1e1e1e;
      }
      div.img span.unread-notification{
        background: #c45606ab;
        backdrop-filter: blur(5px) brightness(1);
        top: 0px;
        left: 0px;
        border-bottom-left-radius: 3px;
        border-bottom-right-radius: 3px;
        outline: 3px solid #f56c08;
        animation: glow 5s infinite;
      }
      @keyframes glow {
        0% {
          outline-color: #f56c08d6;
        }
        50% {
          outline-color: transparent;
        }
        100% {
          outline-color: #f56c08d6;
        }
      }
    .form-container {
        box-sizing: border-box;
        position: fixed;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        max-width: 100vw;
        width: 800px;
        padding: 2.5rem;
        border-radius: .25rem;
        z-index:99999;
        background-color: transparent !important;
        backdrop-filter: blur(1rem) brightness(.8) contrast(1.2)
    }
    .form-container * {
        box-sizing: inherit;
    }
    .textarea-input {
        width: 100%;
        min-height: 10rem;
        padding: 1rem;
        border-radius: .25rem;

        color-scheme: dark !important;
    }
    .buttons-line {
        margin-top: .3rem;
        gap:.3rem;
        width: 100%;
        display: flex;
    }
    .submit-button:hover, .cancel-button:hover{
      filter: brightness(.8) contrast(1.2)
    }
    .submit-button, .cancel-button{
      transform: .3s;
    }
    .submit-button {
        height: 50px;
        flex-grow: 1;
        cursor: pointer;
        border-radius: .25rem;
        color-scheme: dark !important;
        font-weight:bold;
        border:0;
    }
    .cancel-button {
        width:min-content;
        height: 50px;
        cursor: pointer;
        border-radius: .25rem;
        color-scheme: dark !important;
        background-color: red;
        font-weight:bold;
        padding-inline:.5rem;
        border:0;

    }

input.accept-button {
    color: #fff;
    background-image: linear-gradient(rgb(0, 128, 0) 0%, rgb(0, 255, 0) 100%);
}

input.accept-button:hover {
    color: #fff !important;
    background-image: linear-gradient(rgb(34, 139, 34) 0%, rgb(50, 205, 50) 100%) !important;
}

input.reject-button {
    color: #fff;
    background-image: linear-gradient(rgb(255, 0, 0) 0%, rgb(128, 0, 0) 100%);
}

input.reject-button:hover {
    color: #fff !important;
    background-image: linear-gradient(rgb(220, 20, 60) 0%, rgb(178, 34, 34) 100%) !important;
}
#vid_previews {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  height: 150px;
  margin-top: 1rem;
  gap:5px;
}

#vid_previews img {
  flex-shrink: 1;
  height: auto;
}


    `;
    document.head.appendChild(style);



  function makeValidUrlString(inputString) {
    var validString = inputString.replace(/[^\w\s\/-]/g, ''); // Remove special characters
    validString = validString.replace(/[-_]{2,}/g, '-'); // Turn consecutive underscores or hyphens into single hyphens
    validString = validString.replace(/\s+/g, '-'); // Turn spaces into hyphens
    validString = validString.replace(/\//g, '-'); // Turn slashes into hyphens
    return validString;
  }

  function friendRequestSetup(video_title, video_url){
    var vid_code = video_url.replace("https://www.camwhores.tv/videos/", "");
    var parts = vid_code.split("/");
    var videoId = parts[0];
    var code = parts[1];
    localStorage.setItem('last_cum_title', video_title);
    localStorage.setItem('last_cum_vid_id', videoId);
  }

  // add the upload button back
  const nav = document.querySelector('.navigation .primary');
  if (restoreUploadButton && ![...nav.querySelectorAll('a')].some(link => link.textContent.trim().includes('Upload'))) {
    const uploadLink = document.createElement('a');
    uploadLink.href = '/upload-video/';
    uploadLink.style.backgroundColor = '#215521';
    uploadLink.textContent = 'Upload';
    nav.appendChild(uploadLink);
  }



    if (window.location.href == "https://www.camwhores.tv/my/messages/") {










        let fiveMinutesAgo = Date.now() - 5 * 60 * 1000;
        if(refreshMessagePage){
            $(document).ready(function() {
                var linkClicked = parseInt(localStorage.getItem("linkClicked")) > fiveMinutesAgo;
                console.log("Initial linkClicked value:", linkClicked);

                $(window).on("focus", function() {
                    localStorage.setItem("linkClicked", fiveMinutesAgo);
                    linkClicked = false;
                    console.log("Window is focused");
                    if (interval !== null) {
                        clearInterval(interval);
                    }
                });

                if (linkClicked) {
                        console.log("Reloading...");
                        var interval = setInterval(function() {
                            location.reload();
                        }, refreshMessagesTimer);
                }

                $(document).on("click auxclick", "a", function(event) {
                    var href = $(this).attr("href");
                    if (event.button === 0 || event.button === 1) {
                        // alert("You're trying to go to " + href);
                        localStorage.setItem("linkClicked", Date.now());
                        linkClicked = true;
                        console.log("Link clicked. Will refresh");
                    }
                });

                $(window).on("blur", function() {
                    console.log("Window blur event");
                    if (linkClicked) {
                        console.log("Reloading...");
                        var interval = setInterval(function() {
                            location.reload();
                        }, refreshMessagesTimer);
                    }
                });


            });

        }




        function processThumbnails() {
            // console.log("Processing thumbnails");
            var thumbnails = document.querySelectorAll('strong.title');
            if (thumbnails.length === 0) {
                console.log("Thumbnails not found. Retrying in 1000 milliseconds.");
                setTimeout(function() {
                    processThumbnails(); // Retry processing thumbnails
                }, 1000);
                return false; // Return false if thumbnails not found
            }

            thumbnails.forEach(function(thumbnail) {
                var usernameText = thumbnail.textContent.trim();
                if (usernameText) {
                    var usernameLink = document.querySelector('a[title="' + usernameText + '"]');
                    if (usernameLink) {
                        var href = usernameLink.getAttribute('href');
                        var userIdMatch = href.match(/\/(\d+)\/$/);
                        if (userIdMatch && userIdMatch.length > 1) {
                            var userId = userIdMatch[1];
                            var usernameUrl = "https://www.camwhores.tv/members/" + userId + "/";
                            GM_xmlhttpRequest({
                                method: "GET",
                                url: usernameUrl,
                                onload: function(response) {
                                    var parser = new DOMParser();
                                    var htmlDoc = parser.parseFromString(response.responseText, "text/html");
                                    var infoMessage = htmlDoc.querySelector('.info-message');
                                    var usernameLink = document.querySelector('a[title="' + usernameText + '"]');
                                    // console.log(usernameText + ": " + usernameUrl)
                                    // console.log(usernameLink)
                                    if (infoMessage && infoMessage.textContent.includes("is in your friends list.")) {
                                        if (usernameLink) {
                                            var divElement = document.createElement('div');
                                            divElement.classList.add("friends-tag");
                                            divElement.textContent = "Friends ✅";
                                            divElement.style.position = "absolute";
                                            divElement.style.top = "0";
                                            divElement.style.right = "0";
                                            divElement.style.backgroundColor = "#414141"; //#1a1a1a
                                            divElement.style.borderBottomLeftRadius = "3px";
                                            divElement.style.color = "white";
                                            divElement.style.padding = "3px 5px";

                                            if (usernameLink) {
                                                var firstDivElement = usernameLink.querySelector('div.img');
                                                if (firstDivElement) {
                                                    firstDivElement.appendChild(divElement);
                                                }
                                            }
                                        }
                                    }
                                    if(infoMessage && infoMessage.textContent.includes("wants to be your friend.")){
                                        divElement = document.createElement('div');
                                        divElement.textContent = "👀";
                                        divElement.title = "Wants to be your friend!";
                                        divElement.style.position = "absolute";
                                        divElement.style.bottom = "0";
                                        divElement.style.left = "0";
                                        // divElement.style.backgroundColor = "aquamarine";
                                        divElement.style.color = "white";
                                        divElement.style.fontSize = "1rem";
                                        divElement.style.padding = ".5rem .25rem";

                                        if (usernameLink) {
                                            firstDivElement = usernameLink.querySelector('div.img');
                                            if (firstDivElement) {
                                                firstDivElement.appendChild(divElement);
                                            }
                                        }
                                    }

                                    var titleVideosElement = htmlDoc.evaluate('//*[@id="list_videos_uploaded_videos"]/div[1]/h2', htmlDoc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
                                    var videoNumber = 0;

                                    if (titleVideosElement && titleVideosElement.singleNodeValue) {
                                        var titleVideosText = titleVideosElement.singleNodeValue.textContent;
                                        if (titleVideosText) {
                                            var matches = titleVideosText.match(/\(([^)]+)\)/);
                                            videoNumber = matches ? matches[1] : 0;
                                        }
                                    }

                                    if(videoNumber || videoNumber === 0){
                                        divElement = document.createElement('div');
                                        divElement.classList.add("videos-tag");
                                        divElement.textContent = videoNumber;
                                        divElement.style.position = "absolute";
                                        divElement.style.bottom = "0";
                                        divElement.style.right = "0";
                                        divElement.style.backgroundColor = "CadetBlue";
                                        divElement.style.color = "white";
                                        divElement.style.padding = "3px 5px";
                                        divElement.style.borderTopLeftRadius = "3px";
                                    }


                                    if (usernameLink) {
                                        firstDivElement = usernameLink.querySelector('div.img');
                                        if (firstDivElement) {
                                            firstDivElement.appendChild(divElement);
                                        }
                                    }
                                } // end httpGET reponse

                            });
                        } else {
                            console.log("User ID not found in href for:", usernameText);
                        }
                    } else {
                        console.log("Username link not found for:", usernameText);
                    }
                }




            });
            return true; // Return true if thumbnails processed successfully
        }

        // Function to add event listener to buttons
        function addButtonEventListener() {
            console.log("Adding event listener to buttons");
            document.addEventListener('click', function(event) {
                var target = event.target;
                if (target && target.matches('a[data-action="ajax"]')) {
                    // console.log("Button clicked");

                    const h2Element = document.querySelector('#list_members_my_conversations div.headline h2');
                    const initialText = h2Element.textContent.trim();
                    // console.log("Initial text: " + initialText);
                    const checkChangeInterval = setInterval(function() {
                        const h2Element = document.querySelector('#list_members_my_conversations div.headline h2');
                        const currentText = h2Element.textContent.trim();
                        // console.log("Current text: " + currentText);
                        if (currentText !== initialText) {
                            clearInterval(checkChangeInterval);
                            processThumbnails();
                        }
                    }, 100);
                }
            });
        }


        console.log("Calling functions to apply styles and process thumbnails");

        setTimeout(function() {
            processThumbnails();
            var thumbnailsProcessed = processThumbnails();
            if (!thumbnailsProcessed) {
                console.log("Processing thumbnails failed. Retrying in 1000 milliseconds.");
                setTimeout(function() {
                    processThumbnails(); // Retry processing thumbnails
                }, 1000);
            }
            addButtonEventListener();
        }, 1000);




        setInterval(function() {
            processThumbnails()
            console.log("Updating status of users")
        }, 3000);


        const refreshIcon = document.createElement('span');
        refreshIcon.innerHTML = '↻'; // Unicode for refresh icon
        refreshIcon.title = 'Refresh Utilities Mod';
        refreshIcon.style.cursor = 'pointer';
        refreshIcon.style.marginLeft = '10px'; // Adjust margin as needed
        refreshIcon.addEventListener('click', function() {
            processThumbnails()
            console.log('Refreshing...');
        });

        const h2Element = document.querySelector('#list_members_my_conversations .headline h2');
        console.log("adding..?")
        h2Element.appendChild(refreshIcon);




    }else if(window.location.href.startsWith("https://www.camwhores.tv/my/messages/")) {








const textarea = document.querySelector("#send_message_message");
const divTextarea = document.createElement('div');

function copyContentToTextarea() {
    const tempDiv = document.createElement('div');
    tempDiv.innerHTML = divTextarea.innerHTML;

    const content = [];
    tempDiv.childNodes.forEach(node => {
        if (node.nodeType === 3) { // Text node
            content.push(node.textContent);
        } else if (node.nodeType === 1 && node.tagName === 'IMG') { // Image node
            content.push(node.alt);
        }
    });

    const finalText = content.join('').trim(); // Join text content and alt attributes with space

    textarea.value = finalText; // Set the final text to the textarea
}


textarea.style.display = "none";
divTextarea.innerHTML = textarea.value;
divTextarea.contentEditable = true;
divTextarea.style.minHeight = "5rem";
divTextarea.style.resize = "vertical";
divTextarea.style.overflow = "auto";
divTextarea.style.fontSize = "14px";
divTextarea.classList.add("textarea");
textarea.parentNode.insertBefore(divTextarea, textarea.nextSibling);

document.querySelectorAll('.smileys-bar img').forEach(function(img) {
    img.addEventListener('click', function(event) {
        event.preventDefault();
        event.stopPropagation();

        var imgClone = img.cloneNode(true);
        imgClone.style.cursor = "auto"; // Add cursor style

        divTextarea.appendChild(imgClone);
      copyContentToTextarea()
        return false;
    });
});
divTextarea.addEventListener('input', copyContentToTextarea);





var inlineTexts = document.querySelectorAll('span.inline-text, span.original-text');

inlineTexts.forEach(function(span) {
    var lineText = span.textContent.trim();
    if (lineText.includes('##')) {
        var index = lineText.indexOf(':');
        var videoText = lineText.substring(0, index).trim();
        var videoInfo = lineText.substring(index + 1).trim().replace('##', '');
        let parts = videoInfo.split("\n");
        let videoCode = parts[0];
        let videoID = parts[1];
        let url = 'https://www.camwhores.tv/videos/' + videoID + "/" + makeValidUrlString(videoCode) + '/';
        console.log(url)

          fetch(url)
      .then(response => {
        if (response.ok) {
          span.innerHTML = videoText + ': <a href="' + url + '" class="toggle-button" style="display:inline-block">'+videoCode+'</a>';
        } else if (response.status === 404) {
          console.log("URL is 404");
        } else {
          console.error("Error:", response.status);
        }
      })
      .catch(error => console.error("Error:", error));

        // span.innerHTML = videoText + ': <a href="' + url + '" class="toggle-button" style="display:inline-block">Open video</a>';
    }
});





        document.addEventListener('keydown', function(event) {
          if (event.ctrlKey && event.key === 'Enter') {
            event.preventDefault();
            document.querySelector('#send_message_form input[type="submit"]').click();
          }
        });



        function fetchAndExtract(url) {
            GM_xmlhttpRequest({
                method: "GET",
                url: url,
                onload: function(response) {
                  document.evaluate('//*[@id="list_messages_my_conversation_messages_items"]/div/div[3]/img', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue?.remove();

                    // Parse the response text into a HTML document
                    var parser = new DOMParser();
                    var htmlDoc = parser.parseFromString(response.responseText, "text/html");

                    var titleElement = htmlDoc.evaluate('//*[@id="list_videos_uploaded_videos"]/div[1]/h2', htmlDoc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
                    var contentElement = htmlDoc.evaluate('//*[@id="list_videos_uploaded_videos_items"]/div[1]/a/div[3]/div[1]/em', htmlDoc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
                    var joinedDateElement = htmlDoc.evaluate('/html/body/div[2]/div[2]/div/div[2]/div[2]/div/div/div[1]/div[3]/em', htmlDoc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
                    var joinedDateText = joinedDateElement.singleNodeValue.textContent;
                    let imgData = [];
                    for (let i = 1; i <= 5; i++) {
                        let xpath = `/html/body/div[2]/div[2]/div/div[2]/div[3]/div[2]/div/div/div[${i}]/a/div[1]/img`;
                        let img = htmlDoc.evaluate(xpath, htmlDoc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
                        if (img) {
                            imgData.push({ src: img.getAttribute('data-original'), alt: img.alt });
                        }
                    }
                    // console.log(imgData);


                    var confirmButton = document.querySelector('input[name="confirm"]');
                    var rejectButton = document.querySelector('input[name="reject"]');
                    let confirmClose = null
                    let denyClose = null

if (confirmButton) {
    let buttonsParent = confirmButton.parentElement;

    confirmClose = document.createElement('input');
    confirmClose.className = 'submit';
    confirmClose.value = 'Confirm & Close';
    confirmClose.type = 'submit';
    confirmClose.style.margin = '2.5px 3px 0 0';


    denyClose = document.createElement('input');
    denyClose.className = 'submit';
    denyClose.value = 'Deny & Close';
    denyClose.type = 'submit';

    confirmClose.addEventListener('click', function(event) {
        event.preventDefault();
        confirmButton.click();
        window.close();

    });

    denyClose.addEventListener('click', function(event) {
        event.preventDefault();
        rejectButton.click();
        window.close();

    });

    buttonsParent.appendChild(document.createElement('br'));
    buttonsParent.appendChild(confirmClose);
    buttonsParent.appendChild(denyClose);

    let vidPreviewsDiv = document.createElement("div");
    vidPreviewsDiv.id = "vid_previews";

    imgData.forEach(data => {
        let img = document.createElement("img");
        img.src = data.src;
        img.alt = data.alt;
        img.title = data.alt;
        vidPreviewsDiv.appendChild(img);
    });

    buttonsParent.appendChild(vidPreviewsDiv);

}


function updateButtonStyle(button, state) {
    if (state && button) {
        // button.style.backgroundImage = 'linear-gradient(rgb(0, 128, 0) 0%, rgb(0, 255, 0) 100%)';
        // button.style.color = '#fff';
        button.classList.add("accept-button");


    } else if(button) {
        // button.style.backgroundImage = 'linear-gradient(rgb(255, 0, 0) 0%, rgb(128, 0, 0) 100%)';
        // button.style.color = '#fff';
        button.classList.add("reject-button");

    }
}


                    if (titleElement && titleElement.singleNodeValue && contentElement && contentElement.singleNodeValue && joinedDateElement && joinedDateElement.singleNodeValue) {
                        var titleText = titleElement.singleNodeValue.textContent;
                        var extractedTitle = titleText.match(/\(([^)]+)\)/);




                        if (extractedTitle && extractedTitle.length > 1) {
                          // THERE ARE VIDEOS
                            // confirmButton.style.backgroundImage = 'linear-gradient(rgb(0, 128, 0) 0%, rgb(0, 255, 0) 100%)';
                            // confirmButton.style.color = '#fff';

                          updateButtonStyle(confirmButton, true)
                          updateButtonStyle(confirmClose, true)

                            var contentText = contentElement.singleNodeValue.textContent;
                            var generatedText = "<div id=gen_joined_text>Joined " + joinedDateText + "<br>" + extractedTitle[1] + " videos, last " + contentText + "</div>";
                            // Add generated text to the visible page
                            var messageDiv = document.evaluate('//*[@id="list_messages_my_conversation_messages_items"]/div/div[3]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
                            if (messageDiv && messageDiv.singleNodeValue) {
                                messageDiv.singleNodeValue.innerHTML += generatedText;
                            }
                        } else {
                            console.log('Text inside parentheses in title not found.');
                        }
                    } else {
                        // THERE ARE NO VIDEOS
                        console.log('Title, content, or joined date element not found. Probably no videos uploaded yet.');
                        // rejectButton.style.backgroundImage = 'linear-gradient(rgb(255, 0, 0) 0%, rgb(128, 0, 0) 100%)';
                        // rejectButton.style.color = '#fff';
                        updateButtonStyle(rejectButton, false)
                        updateButtonStyle(denyClose, false)
                        messageDiv = document.evaluate('//*[@id="list_messages_my_conversation_messages_items"]/div/div[3]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
                        if (messageDiv && messageDiv.singleNodeValue) {
                            messageDiv.singleNodeValue.innerHTML += "<div id=gen_joined_text>Joined " + joinedDateText + "<br><b>No videos</b></div>";
                        }
                    }
                }
            });
        }

        var bottomDiv = document.querySelector("#send_message_form > div > div.bottom");
        var responsesDiv = document.createElement("div");
        responsesDiv.id = "responses";
        responsesDiv.style.marginTop = "1rem";
        bottomDiv.insertAdjacentElement('afterend', responsesDiv);


        auto_replies.forEach(function(string) {
            var button = document.createElement("button");
            button.textContent = string;
            button.classList.add("button");
            button.addEventListener("click", function(event) {
                event.preventDefault();
                if (textarea.value.trim() !== '') {
                    textarea.value += "\n";
                }
                textarea.value += string;
                document.querySelector('#send_message_form').submit();
            });
            button.style.padding = ".25rem .5rem"
            responsesDiv.appendChild(button);
        });




        // var messageLink = document.evaluate('//*[@id="list_messages_my_conversation_messages"]/div[1]/h2/a[2]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
        var messageLink = document.evaluate('//*[@id="list_messages_my_conversation_messages_items"]/div/div[1]/a', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);

        if (messageLink && messageLink.singleNodeValue) {
            var messageUrl = messageLink.singleNodeValue.href;

            const parentElement = document.evaluate('//*[@id="list_messages_my_conversation_messages_items"]/div/div[3]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
            const img = document.createElement('img');
            img.src = 'https://samherbert.net/svg-loaders/svg-loaders/three-dots.svg';
            img.style.height = "32px";
            img.style.width = "32px";
            parentElement.appendChild(img);
            fetchAndExtract(messageUrl); // SENDING ACTUAL REQUEST
        } else {
            console.log('Message link not found.');
        }


        // AESTHETIC CHANGE
        var bottomElement = document.evaluate('//*[@id="list_messages_my_conversation_messages_items"]/div/div[3]/form/div', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
        if (bottomElement && bottomElement.singleNodeValue) {
            bottomElement.singleNodeValue.style.marginTop = "1em";
            bottomElement.singleNodeValue.style.marginBottom = "1em";
            bottomElement.singleNodeValue.classList.remove("bottom");
        } else {
            console.log('Bottom element not found.');
            setTimeout(function() {
                var gen_joined_text = document.getElementById('gen_joined_text');
                if (gen_joined_text) gen_joined_text.innerHTML = "<br>" + gen_joined_text.innerHTML;

            }, 200); // Adjust the delay time as needed
        }





    }else if(window.location.href !== "https://www.camwhores.tv/my/videos/") {
        // Set to store unique video elements
        const processedVideos = new Set();

        function addPrivateVideos() {
            const private_videos = [];

            const videoElements = document.querySelectorAll('.line-premium, .line-private');

            videoElements.forEach(video => {
                const parentDiv = video.parentElement;
                if (
                    parentDiv.tagName === 'DIV' &&
                    parentDiv.parentElement.tagName === 'A' &&
                    !processedVideos.has(parentDiv.parentElement)
                ) {
                    private_videos.push(parentDiv.parentElement);
                    processedVideos.add(parentDiv.parentElement);
                }
            });

            return private_videos;
        }

async function checkVideoPage(url) {
    try {
        const response = await fetch(url);
        // Check if the response status code indicates an error
        if (!response.ok) {
            console.error('Error loading video page:', response.status);
            return { byFriend: true, usernameID: null }; // Return true if there's an error loading the page
        }

        const html = await response.text();
        const parser = new DOMParser();
        const doc = parser.parseFromString(html, 'text/html');
        const hasElement1 = doc.querySelector('body > div.container > div.content > div.block-video > div.video-holder > div.player > div > div > span') !== null;
        const hasElement2 = doc.querySelector('body > div.container > div.content > div.block-album > div.album-holder > div.images > span.message') !== null;
        //                                     basically the "This video is a private video uploaded by" message
        const userURL = doc.querySelector('.username a').href;
        var vid_code = userURL.replace("https://www.camwhores.tv/members/", "");
        var usernameID = vid_code.split("/")[0];

        return { byFriend: hasElement1 || hasElement2, usernameID: usernameID };
    } catch (error) {
        console.error('Error checking video page:', error);
        return { byFriend: false, usernameID: null };
    }
}


        async function applyStyleToPrivateVideos() {
            const privateVideos = addPrivateVideos();
            for (const video of privateVideos) {

                let videoLink = video.getAttribute('href');
                let videoTitle = video.querySelector('strong.title').textContent.trim();
                let { byFriend: hasElement, usernameID } = await checkVideoPage(videoLink);
                // console.log(videoLink + " " + hasElement);
                if (!hasElement) {
                    video.style.outline = 'green solid 2px';
                    const linePrivate = video.querySelector('div > .line-private');
                    if (linePrivate) {
                        linePrivate.style.display = 'none';
                    }
                    let imgElement = video.querySelector('div > img');
                    if (imgElement) {
                        imgElement.style.opacity = '1';
                    }
                }else{
                    // add ❌
                    const linePrivate = video.querySelector('div > .line-private > span');
                    if (linePrivate) {
                        linePrivate.textContent += ' ❌';
                        const addFriend = document.createElement('a');
                        addFriend.textContent = '➕';
                        addFriend.title = 'Friend request';
                        addFriend.href = "https://www.camwhores.tv/members/" + usernameID + "/#friends";
                        addFriend.style.zIndex = '10';
                        addFriend.style.position = 'absolute';
                        addFriend.style.bottom = '20px';
                        addFriend.style.right = '0';
                        addFriend.style.fontSize = '1rem';
                        addFriend.style.padding = '5px 2.5px';
                        addFriend.style.backgroundColor = 'hsla(0, 0%, 0%, 0.7)';
                        addFriend.addEventListener('click', function(event) {
                            alert(videoTitle)
                            friendRequestSetup(videoTitle, videoLink)
                        });


                        let thumbDiv = video.querySelector('.img')
                        thumbDiv.appendChild(addFriend);
                      // video.style.outline = "2px solid red"
                    }
                }
                await new Promise(resolve => setTimeout(resolve, 25)); // avoid 503
            }
        }
        applyStyleToPrivateVideos();

        function findRelevantKeywords() {
            const titles = document.querySelectorAll('.title');
            titles.forEach(title => {
                const originalText = title.innerHTML;
                highlight_keywords.forEach(keyword => {
                    const regex = new RegExp(keyword, 'gi');
                    if (originalText.match(regex)) {
                        const highlightedText = originalText.replace(regex, '<span style="color: green;">$&</span>');
                        title.innerHTML = highlightedText;
                    }
                });
            });
        }
        findRelevantKeywords()



// Define a global array to store blacklisted image sources
const blacklist = [];

function moveToSecondThumbnail() {
    $('.thumb.lazy-load').off('mouseover').off('mouseout');

    document.querySelectorAll('.thumb.lazy-load').forEach(image => {
        const src = image.getAttribute('src');
        if (blacklist.includes(src)) {
            return;
        }
        const newSrc = src.replace('1.jpg', '2.jpg');
        // console.log("ye")
        if (src && src.endsWith('1.jpg')) {
            image.setAttribute('src', newSrc);
        }

        const images = ['3.jpg', '4.jpg', '5.jpg', '1.jpg', '2.jpg'];
        let currentIndex = 0;
        let intervalId;

        const loopImages = () => {
          if (src && src.endsWith('jpg')) {
            const newSrcName = images[currentIndex];
            const newSrc = src.substring(0, src.length - 5) + newSrcName;
            console.log(newSrc)
            image.setAttribute('src', newSrc);
            currentIndex = (currentIndex + 1) % images.length;
          }
        };

        const mouseoverHandler = () => {
            clearInterval(intervalId);
            intervalId = setInterval(loopImages, 500);
        };


        const mouseoutHandler = () => {
            if (src && src.endsWith('1.jpg') && !(blacklist.includes(src))) {
                image.setAttribute('src', newSrc);
            }
          clearInterval(intervalId);
        };

        // Create a new image element to check if the original image was loaded successfully
        const testImage = new Image();
        testImage.src = src;

        testImage.onload = function() {
            // Image loaded successfully
            // console.log('Image loaded successfully:', src);
        };

        testImage.onerror = function() {
            // Image failed to load (404 error)
            // console.log('Image failed to load (404 error):', src);
            blacklist.push(src);
            image.setAttribute('src', src);

            // Remove previous mouseover and mouseout event listeners
            image.removeEventListener('mouseover', mouseoverHandler);
            image.removeEventListener('mouseout', mouseoutHandler);
        };



        // Add mouseover and mouseout event listeners
        image.addEventListener('mouseover', mouseoverHandler);
        image.addEventListener('mouseout', mouseoutHandler);
    });
    // console.log(blacklist);
}





        altThumbs && moveToSecondThumbnail();

        setInterval(() => {
            applyStyleToPrivateVideos();
            findRelevantKeywords()
            altThumbs && moveToSecondThumbnail();
        }, 750); // Interval in milliseconds (every second)



        if (window.location.href.startsWith("https://www.camwhores.tv/members/")) {
            console.log("NOT messages, user PROFILE");

          function updateH2Element() {
                const h2Element = document.querySelector('#list_videos_uploaded_videos .headline h2');

                if (h2Element) {
                    const text = h2Element.textContent;
                    const startIndex = text.indexOf('(');
                    const endIndex = text.indexOf(')', startIndex);

                    if (startIndex !== -1 && endIndex !== -1 && text.includes("Page")) {
                        const videos_total = parseInt(text.substring(startIndex + 1, endIndex));
                        const rounded_videos_total = Math.ceil(videos_total / 5);
                        const innerHTML = h2Element.innerHTML.trim();
                        if (!innerHTML.includes('/')) {
                            h2Element.innerHTML = innerHTML + '/' + rounded_videos_total;
                        }
                    }
                }
            }

            function addButtonEventListener() {
                console.log("Adding event listener to buttons");
                document.addEventListener('click', function(event) {
                    var target = event.target;
                    if (target && target.matches('a[data-action="ajax"]')) {
                        // console.log("Button clicked");

                        const h2Element = document.querySelector('#list_videos_uploaded_videos .headline h2');
                        const initialText = h2Element.textContent.trim();
                        // console.log("Initial text: " + initialText);
                        const checkChangeInterval = setInterval(function() {
                            const h2Element = document.querySelector('#list_videos_uploaded_videos .headline h2');
                            const currentText = h2Element.textContent.trim();
                            // console.log("Current text: " + currentText);
                            if (currentText !== initialText) {
                                clearInterval(checkChangeInterval);
                                updateH2Element();
                            }
                        }, 100);
                    }
                });
            }


            updateH2Element()
            addButtonEventListener()

      // console.log(friend_request_text)

      if (window.location.href.endsWith("#friends") && !window.location.href.includes("add_to_friends_done")) {
          let addButton = document.querySelector('a[href="#friends"][data-action="add_to_friends"]');
          let textarea = document.getElementById('add_to_friends_message');
          let lastCumTitle = localStorage.getItem('last_cum_title');
          let lastVidCode = localStorage.getItem('last_cum_vid_id');
          let lastCumUsername = localStorage.getItem('last_cum_username_fr');
          let pageTitle = document.title;
          let username = pageTitle.replace("'s Page", "");
          if (textarea !== null && !addButton.classList.contains('done') && username !== lastCumUsername && lastCumTitle !== null && addButton !== null) {
              textarea.value = "";
              textarea.value += friend_request_text + " " + lastCumTitle + "\n##" + lastVidCode;
              console.log("Textarea text set");
              document.querySelector('input[type="submit"].submit[value="Invite"]').click();
              localStorage.setItem('last_cum_username_fr', username);
              addButton.click();
          }
      }else if(window.location.href.includes("add_to_friends_done")){
          let addButton = document.querySelector('a[href="#friends"][data-action="add_to_friends"]');
          if (addButton !== null && !addButton.classList.contains('done')) {
                  addButton.classList.add('done');
              }
      }


  } // END of member profile




        if(window.location.href.startsWith("https://www.camwhores.tv/videos/")){
            const element1 = document.querySelector('body > div.container > div.content > div.block-video > div.video-holder > div.player > div > div > span');
            const element2 = document.querySelector('body > div.container > div.content > div.block-album > div.album-holder > div.images > span.message');

            if (element1 !== null || element2 !== null) {
                const href = document.querySelector('#tab_video_info > div > div.block-user > div > a').href;

                fetch(href)
                    .then(response => response.text())
                    .then(html => {
                    const htmlDoc = new DOMParser().parseFromString(html, 'text/html');
                    const infoMessage = htmlDoc.querySelector('.info-message');
                    if (infoMessage && infoMessage.textContent.includes("is in your friends list.")) {
                        const friends_string = "You're already friends! Reloading in 4 seconds";
                        (element1 || element2).textContent = friends_string;
                        setInterval(() => {
                            location.reload();
                        }, 4000);
                    } else {
                        var infoElement = null;
                        if(element1 !== null){
                          infoElement = element1
                        }else{
                          infoElement = element2
                        }
                        console.log("Not friends!");
                        let headline = document.querySelector('body > div.container > div.content > div.headline > h1');
                        if (headline !== null) {
                            let title = headline.textContent.trim();
                            // localStorage.setItem('last_cum_title', title);
                            var currentUrl = window.location.href;
                            friendRequestSetup(title, currentUrl);
                            // var vid_code = currentUrl.replace("https://www.camwhores.tv/videos/", "");
                            // var parts = vid_code.split("/");
                            // var videoId = parts[0];
                            // var code = parts[1];
                            // localStorage.setItem('last_cum_vid_id', videoId);

                            // console.log("vid_code:"+vid_code)
                            // console.log("Video ID: " + videoId);
                            // console.log("code:\n" + code + "\n"+makeValidUrlString(code));
                            const userProfileUrl = infoElement.querySelector('a').getAttribute('href') + "#friends";
                            console.log(userProfileUrl)
                            const toggleButton = document.createElement('a');
                            toggleButton.classList.add("button");
                            toggleButton.textContent = "Send request";
                            toggleButton.href = userProfileUrl
                            toggleButton.style.display= "inline-block";
                            toggleButton.style.display= "#4e4e4e";
                            infoElement.appendChild(document.createElement('br'));
                            infoElement.appendChild(toggleButton);
                        } else {
                            console.log("Element not found");
                        }


                    }
                })
                    .catch(error => console.error('Error fetching:', error));
            }
        }

    }
})();