Camwhores.tv Utilities Mod

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

Verze ze dne 24. 05. 2024. Zobrazit nejnovější verzi.

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

    }
})();