Camwhores.tv Utilities Mod

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

As of 2024-06-03. See the latest version.

// ==UserScript==
// @name         Camwhores.tv Utilities Mod
// @namespace    https://sleazyfork.org/users/1281730-vipprograms
// @version      1.7.4
// @description  Info preview, removal of lock from friends' vidoes, restored upload button, and more.
// @author       vipprograms
// @match        https://www.camwhores.tv/*
// @exclude      *.camwhores.tv/*mode=async*
// @grant        GM_xmlhttpRequest
// @grant        GM.getValue
// @grant        GM_getValue
// @grant        GM.setValue
// @grant        GM_setValue
// @grant        GM_registerMenuCommand
// @grant        GM.registerMenuCommand
// @grant        GM_addStyle
// @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, _GM_notification, options, optionName;
    const refreshVideosMinutes = 30;


    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); };
      console.log("Oh no");
    }



    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")

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

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

    optionName = "notify me of processed videos";
    toggleChange(options, optionName, false)
    var notifyProcessedVideos = retrieveValueFromStorage("options")[optionName];



    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, span.accept-button {color: #fff;background-image: linear-gradient(rgb(0, 128, 0) 0%, rgb(0, 255, 0) 100%);}input.accept-button:hover, span.accept-button:hover {color: #fff !important;background-image: linear-gradient(rgb(34, 139, 34) 0%, rgb(50, 205, 50) 100%) !important;}input.reject-button, span.reject-button {color: #fff;background-image: linear-gradient(rgb(255, 0, 0) 0%, rgb(128, 0, 0) 100%);}input.reject-button:hover, span.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;height: 135px;margin-block: .5rem;gap: 5px;box-sizing: border-box;}#vid_previews .img-div {width:185px;height:100%;position: relative;box-sizing: inherit;}.list-messages .added {position: absolute;right: 0;}.list-messages .item {margin-right: 0;}#vid_previews .img-div img{box-sizing: inherit;width: 100%;height:100%;}#vid_previews .img-div h2{position: absolute;bottom: 0;background-color: rgb(0 0 0 / 65%);font-size: 1rem;line-height: 1.2rem;backdrop-filter: blur(5px);color: rgb(196 196 196);width: 100%;word-wrap: break-word;box-sizing: inherit;text-align: center;}.bottom-element{margin-top: 1em;margin-bottom: 1em;}form .bottom{padding-top: .5rem;}form .bottom .submit{float: initial;height: auto;padding: .45rem .5rem;margin: 0;}.margin-fix .bottom{margin:0;}#gen_joined_text{margin: .5rem 0 .25rem 0;}a[href="http://flowplayer.org"], a[class="fp-brand"]{opacity: 0 !important;pointer-events: none !important;}div.block-profile > div > div > div.about-me > div > em{white-space:pre;}
h1.online:after{
    content: '';
    height: .45rem;
    aspect-ratio: 1;
    display: inline-block;
    background-color: green;
    position: relative;
    left: .5rem;
    border-radius: 50%;
    bottom: .1rem;
}
`;
    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, userID){
    var vid_code = video_url.replace("https://www.camwhores.tv/videos/", "");
    var parts = vid_code.split("/");
    var videoId = parts[0];
    var code = parts[1];
    let cumData = {
        title: video_title,
        videoId: videoId,
        userId: userID
    };
    localStorage.setItem('last_cum_video_add', JSON.stringify(cumData));
  }

       function convertToSeconds(timeString) {
    let [_, value, unit] = timeString.match(/(\d+) (\w+)/);
    value = parseInt(value);
    switch (unit) {
        case 'second':
        case 'seconds':
            return value;
        case 'minute':
        case 'minutes':
            return value * 60;
        case 'hour':
        case 'hours':
            return value * 3600;
        case 'day':
        case 'days':
            return value * 86400;
        case 'week':
        case 'weeks':
            return value * 604800;
        case 'month':
        case 'months':
            return value * 2592000; // assuming 30 days per month
        case 'year':
        case 'years':
            return value * 31536000; // assuming 365 days per year
        default:
            return 0;
    }
}


function fetchAndParseHTML(url, callback) {
    GM_xmlhttpRequest({
        method: "GET",
        url: url,
        onload: function(response) {
            var parser = new DOMParser();
            var htmlDoc = parser.parseFromString(response.responseText, "text/html");
            callback(htmlDoc);
        }
    });
}


function fetchAndExtract(url, callback) {
    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();

            var parser = new DOMParser();
            var htmlDoc = parser.parseFromString(response.responseText, "text/html");

            callback(htmlDoc);
        }
    });
}
/*
  usage:

fetchAndExtract(messageUrl, function(htmlDoc) {
});

 */
function getAllSessionStorage() {
  var sessionStorageItems = {};
  for (var i = 0; i < sessionStorage.length; i++) {
    var key = sessionStorage.key(i);
    var value = sessionStorage.getItem(key);
    sessionStorageItems[key] = value;
  }
  return sessionStorageItems;
}

function getCurrentPage(){
    var allSessionStorage = getAllSessionStorage();
    var paramsStorageKey = Object.keys(allSessionStorage).find(key => key.endsWith(":params"));
    if(!allSessionStorage || !paramsStorageKey){
      return 1;
    }
    // console.log(allSessionStorage)
    // console.log("paramsStorageKey:",paramsStorageKey)
    var paramsValue = JSON.parse(allSessionStorage[paramsStorageKey]).from_my_conversations;
    // console.log("getCurrentPage:",getCurrentPage)
    return paramsValue;
}

function getCookie(name) {
    let cookieArr = document.cookie.split("; ");
    for(let cookie of cookieArr) {
        let [key, value] = cookie.split("=");
        if(key === name) return value;
    }
    return null;
}

function loadArrayLocalStorage(name='lastVideoData') {
    var jsonData = localStorage.getItem(name);
    if (!jsonData) {
        return [];
    }

    var data = JSON.parse(jsonData);
    return data;
}

function saveArrayLocalStorage(name='lastVideoData', data){
    var timestamp = Date.now();
    var jsonData = JSON.stringify(data);
    localStorage.setItem(name, jsonData);
}



function getNewUID() {
    let sessionStorageData = getAllSessionStorage();
    if(!sessionStorageData){
      return null;
    }
    for (let key in sessionStorageData) {
        let matches = key.match(/^(\d+):https:\/\/www\.camwhores\.tv/);
        if (matches) {
            return matches[1];
        }
    }
    return null;
}

function saveUID(){
    let uid = getNewUID();
    if(uid){
        let current_kt = getCookie("kt_member");
        let data = {uid: uid, kt: current_kt};
        saveArrayLocalStorage("cum_user_id", data);
        return uid;
    }
    return
}

function silentUidUpdater(){
    let uidArray = loadArrayLocalStorage("cum_user_id");
    if(!uidArray || getCookie("kt_member") !== uidArray.kt){
        saveUID();
    }
}

function currentUserID(){
    let current_kt = getCookie("kt_member");
    let uidArray = loadArrayLocalStorage("cum_user_id");

    if(uidArray && uidArray.kt === current_kt){
        return uidArray.uid;
    }else{
        return saveUID()
    }
    return
}

async function getResponseStatus(url) {
    try {
        let response = await fetch(url, { method: 'HEAD' });
        return response.status;
    } catch (error) {
        return null;
    }
}


let currentUID = currentUserID();
// console.log("User ID:", currentUID, "(https://www.camwhores.tv/members/" + currentUID + "/)")

silentUidUpdater()

// UPLOAD button
const nav = document.querySelector('.navigation .primary');
if (nav && restoreUploadButton && ![...nav.querySelectorAll('a')].some(link => link.textContent.trim().includes('Upload'))) {
  const uploadLink = document.createElement('div');
  uploadLink.style.backgroundColor = '#215521';
  uploadLink.style.display = 'block';
  uploadLink.style.padding = '11px 0';
  uploadLink.style.cursor = 'pointer';
  uploadLink.textContent = 'UPLOAD';
  nav.appendChild(uploadLink);

  let uploadURL = '/upload-video/'; //'https://www.camwhores.tv/upload-video/'
  uploadLink.addEventListener('click', function() {
      getResponseStatus(uploadURL).then(status => {
          if (status === 200) {
              window.location.href = url;
          } else {
              alert("Upload functionality is currently fully disabled\n(" + status.toString() + ")");
              // console.log(status)
          }
      });
  });




}else{
  console.log("Couldn't restoreUploadButton", restoreUploadButton)
}

     if ((window.location.href.endsWith("?action=reject_add_to_friends_done")) ||
        (window.location.href.endsWith("?action=confirm_add_to_friends_done"))) {

        let urlOfUser = document.querySelector('#list_messages_my_conversation_messages > div.headline > h2 > a:nth-child(2)')
        let username = urlOfUser.innerHTML.trim();
        let userID = urlOfUser.getAttribute('href').match(/\/(\d+)\//)[1];


        const storedData = JSON.parse(localStorage.getItem('closedWindow'));
        if (storedData) {
          let { uid, timestamp } = storedData;
          let currentTime = Date.now();
          let timeDifference = (currentTime - timestamp) / 1000; // in seconds
          console.log(timeDifference + " seconds, uid: "+userID+" vs "+uid)
          if (timeDifference < 30 && userID == uid) {
            console.log(`Less than 30 seconds have passed since window closed. User ID: ${uid}`);
            window.close();
          }else{
          }
        }







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

      function myMessagesAsyncURL(pageInt=1){
        const utcTimestamp = new Date().getTime();
        const pageID = pageInt.toString();
        return "https://www.camwhores.tv/my/messages/?mode=async&function=get_block&block_id=list_members_my_conversations&sort_by=added_date&from_my_conversations="+pageID+"&_="+utcTimestamp;
      }
      // console.log(myMessagesAsyncURL())






    function currentPageInfo() {
      let urlToPage = myMessagesAsyncURL(getCurrentPage());
      // console.log(urlToPage)
      return new Promise((resolve, reject) => {
        fetchAndExtract(urlToPage, function(htmlDoc) {
          const conversations = [];
          const items = htmlDoc.querySelectorAll("#list_members_my_conversations_items .item");
          // console.log("htmlDoc:",htmlDoc)
          items.forEach(item => {
            const name = item.querySelector('a').getAttribute('title');
            const unread = item.classList.contains('unread');
            conversations.push({ name, unread });
          });
          resolve(conversations);
        });
      });
    }

async function fixUnreadItem() {
  const infoArray = await currentPageInfo();
  infoArray.forEach(item => {
    const conversationLink = document.querySelector(`#list_members_my_conversations_items > div.item > a[title="${item.name}"]`);
    if (conversationLink) {
      const unreadNotification = conversationLink.querySelector('div.img .unread-notification');
      if (unreadNotification && !item.unread) {
        unreadNotification.remove();
        console.log("Message with",item.name,"was read")
      }
    }
  });
}


// fixUnreadItem();



        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 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");

                    var h2Element = document.querySelector('#list_members_my_conversations div.headline h2');
                    const initialText = h2Element.textContent.trim();
                    // console.log("Initial text: " + initialText);
                    const checkChangeInterval = setInterval(function() {
                        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);
                }
            });
        }


        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()
            fixUnreadItem()
            silentUidUpdater()
        }, 5000);


        const refreshIcon = document.createElement('span');
        refreshIcon.innerHTML = '&#8635;'; // 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/")) {

        function updateButtonStyle(button, state) {
            if (state && button) {
                button.classList.add("accept-button");
            } else if(button) {
                button.classList.add("reject-button");
                // console.log(button)
            }else{
              // console.log(button + " button absent")
            }
        }

        let textarea = document.querySelector("#send_message_message");
        let divTextarea = document.createElement('div');
        let urlOfUser = document.querySelector('#list_messages_my_conversation_messages > div.headline > h2 > a:nth-child(2)')
        let username = urlOfUser.innerHTML.trim();
        let userID = urlOfUser.getAttribute('href').match(/\/(\d+)\//)[1];
        let confirmButton = document.querySelector('input[name="confirm"]');
        let rejectButton = document.querySelector('input[name="reject"]');
        let buttonsParent = confirmButton ? confirmButton.parentElement : null;
        let confirmClose = null
        let denyClose = null

        // console.log(userID)


        document.querySelector('input.submit').addEventListener('click', function() {
          divTextarea.innerHTML = '';
        });

$(document).ready(function() {
  $(document).keyup(function(event) {
    if (event.ctrlKey && event.key === 'Enter') {
      event.preventDefault();
      alert("Submitting");
      $("#send_message_form").submit();
    }
  });
});



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







          function andClosePage(){
                            const closedWindow = {
                              uid: userID,
                              timestamp: Date.now()
                            };
                            localStorage.setItem('closedWindow', JSON.stringify(closedWindow));

                            console.log("Window should close now")
                            window.close();
                        }



function addCloseButtonsListeners(confirmButton, rejectButton) {
    var confirmClose, denyClose;

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

        confirmClose = document.createElement('span');
        confirmClose.className = 'submit button';
        confirmClose.innerHTML = 'Confirm & Close';

        denyClose = document.createElement('span');
        denyClose.className = 'submit button';
        denyClose.innerHTML = 'Deny & Close';

        confirmClose.addEventListener('click', function(event) {
            event.preventDefault();
            // alert("Clicked! (when done debugging, REMOVE and CLOSE)")
            confirmButton.click();
            andClosePage()
        });
        denyClose.addEventListener('click', function(event) {
            event.preventDefault();
            // alert("Clicked! (when done debugging, REMOVE and CLOSE)")
            rejectButton.click();
            andClosePage()
        });

        var closeButtonsContainer = document.createElement('div');
        closeButtonsContainer.classList.add('closeInputs');
        buttonsParent.appendChild(confirmClose);
        buttonsParent.appendChild(document.createTextNode(' '));
        buttonsParent.appendChild(denyClose);
        buttonsParent.appendChild(closeButtonsContainer);


        confirmButton.style.width = confirmClose.offsetWidth + 'px';
        rejectButton.style.width = denyClose.offsetWidth + 'px';
    }

    return {
        confirmClose: confirmClose,
        denyClose: denyClose
    };
}






function updateMessageDOM(htmlDoc, confirmClose, denyClose) {
    var titleText = htmlDoc.querySelector('#list_videos_uploaded_videos > div:nth-child(1) > h2')?.textContent.trim();
    var lastUploadTime = htmlDoc.querySelector('#list_videos_uploaded_videos_items > div.item > a > div.wrap > div.added > em')?.textContent.trim();
    var joinedDateText = htmlDoc.querySelector('div.block-profile > div.profile-list > div.margin-fix > div.column > div:nth-child(3) > em')?.textContent.trim();
    var lastLogin = htmlDoc.querySelector('div.block-profile > div.profile-list > div.margin-fix > div.last-login > div.item')?.textContent.trim();
    let seconds = convertToSeconds(lastLogin);
    let recentlyOnline = seconds <= 300;
    // let recentlyOnline = true;
    const headlineH2 = document.querySelector('#list_messages_my_conversation_messages .headline h2');
    console.log("recentlyOnline:", recentlyOnline);

    if(recentlyOnline){
      GM_addStyle(`.list-messages .item.new .added:after {
          background-color: green;
        }`);

      document.querySelector("#list_messages_my_conversation_messages_items > div.item.new > div.added").textContent += " (online)";
      headlineH2.innerHTML += " (online)"

    }

    if (titleText) { // THERE ARE VIDEOS
        var extractedTitle = titleText.match(/\(([^)]+)\)/);
        if (extractedTitle && extractedTitle.length > 1) {
            // THERE ARE VIDEOS
            updateButtonStyle(confirmButton, true);
            updateButtonStyle(confirmClose, true);

            var generatedTextDiv = document.createElement('div');
            generatedTextDiv.id = 'gen_joined_text';
            generatedTextDiv.innerHTML = `Joined ${joinedDateText}<br>${extractedTitle[1]} videos, last ${lastUploadTime}`;
            var messageDiv = document.querySelector('#list_messages_my_conversation_messages_items > div > div:nth-child(3)');
            if (messageDiv) {
                messageDiv.appendChild(generatedTextDiv);
            }
        }


              if(confirmClose){
                    let imgData = [];
                    for (let i = 1; i <= 5; i++) {
                        let xpath = `//*[@id="list_videos_uploaded_videos_items"]/div[${i}]/a/div[@class="img"]/img`;
                        let img = htmlDoc.evaluate(xpath, htmlDoc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
                        if (img) {
                            let parentAnchor = img.parentNode.parentNode;
                            imgData.push({ src: img.getAttribute('data-original'), alt: img.alt, url: parentAnchor.getAttribute('href') });
                        }
                    }
                        let vidPreviewsDiv = document.createElement("div");
                        vidPreviewsDiv.id = "vid_previews";
                        if (!isArrayEmpty(imgData)) {
                            imgData.forEach(data => {
                                let imgDiv = document.createElement("div");
                                imgDiv.classList.add("img-div");
                                let imgLink = document.createElement("a"); // New line
                                imgLink.href = data.url; // New line
                                let img = document.createElement("img");
                                img.src = data.src;
                                img.alt = data.alt;
                                img.title = data.alt;
                                let title = document.createElement("h2");
                                title.textContent = data.alt;
                                imgLink.appendChild(img); // Updated line
                                imgDiv.appendChild(imgLink); // Updated line
                                imgDiv.appendChild(title);

                                vidPreviewsDiv.appendChild(imgDiv);
                            });

                            buttonsParent.appendChild(vidPreviewsDiv);
                        }

                }


    } else {
        // THERE ARE NO VIDEOS
        console.log('No videos? Title: '+titleText+", content: "+lastUploadTime);
        updateButtonStyle(rejectButton, false);
        updateButtonStyle(denyClose, false);

        var messageDiv = document.querySelector('#list_messages_my_conversation_messages_items > div > div:nth-child(3)');
        if (messageDiv) {
            var generatedTextDiv = document.createElement('div');
            generatedTextDiv.id = 'gen_joined_text';
            generatedTextDiv.innerHTML = `Joined ${joinedDateText}<br><b>No videos</b>`;
            messageDiv.appendChild(generatedTextDiv);
        }
    }

}



// return


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


// return

        // 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'; // loading spinner
            img.style.height = "32px";
            img.style.width = "32px";
            parentElement.appendChild(img);
            fetchAndExtract(messageUrl, function(htmlDoc) {
                var closeButtons = addCloseButtonsListeners(confirmButton, rejectButton);
                var confirmClose = closeButtons.confirmClose;
                var denyClose = closeButtons.denyClose;
                updateMessageDOM(htmlDoc, confirmClose, denyClose);

            });
        } 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).singleNodeValue;
        if (bottomElement && bottomElement.singleNodeValue) {
            bottomElement.classList.add('bottom-element');
            bottomElement.singleNodeValue.style.marginTop = "1em";
            bottomElement.singleNodeValue.style.marginBottom = "1em";
            bottomElement.singleNodeValue.style.outline = "2px solid red";
            bottomElement.singleNodeValue.classList.remove("bottom");
        }





    }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)
                            event.stopImmediatePropagation();
                            friendRequestSetup(videoTitle, videoLink, usernameID)
                        });


                        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/")) {
            // USER PROFILE

          function userProfileAsyncURL(uid,pageInt){
              const utcTimestamp = new Date().getTime();
              const pageID = pageInt.toString();
              return "https://www.camwhores.tv/members/"+uid+"/?mode=async&function=get_block&block_id=list_videos_uploaded_videos&sort_by=&from_videos="+pageID+"&_="+utcTimestamp;
            }
          function numberBetweenParenthesis(text){
              if(!text){
                return
              }
              const matches = text.match(/\((\d+)\)/);
              if (matches && matches.length > 1) {
                  return parseInt(matches[1]);
              }
              return null;
          }
          function getRoundedTotalPages(userVideosH2) {
              const text = userVideosH2?.textContent;
              let videos_total = numberBetweenParenthesis(text);
              return Math.ceil(videos_total / 5);
          }
          // console.log("getRoundedTotalPages():",getRoundedTotalPages(userVideosH2));


          function updateVideoH2() {
              let userVideosH2 = document.querySelector('#list_videos_uploaded_videos .headline h2');
              if(!userVideosH2){
                return;
              }
              const rounded_videos_total = getRoundedTotalPages(userVideosH2);
              let newText = '/' + rounded_videos_total;

              // console.log(userVideosH2)
              if (rounded_videos_total !== null) {
                  const innerHTML = userVideosH2.innerHTML.trim();
                  if (innerHTML.includes("Page")) {
                      userVideosH2.innerHTML = innerHTML + newText;
                  }
              }else{
                console.log("rounded_videos_total is null inside updateVideoH2()")
              }

              return newText;

          }


          const userVideosH2 = document.querySelector('#list_videos_uploaded_videos .headline h2');
          const rounded_videos_total = getRoundedTotalPages(userVideosH2);
          const userDescription = document.querySelector("div.block-profile > div.profile-list > div > div.about-me > div > em")
          const lastLogin = document.querySelector('div.block-profile > div.profile-list > div.margin-fix > div.last-login > div.item')?.textContent.trim();
          const userId = window.location.href.split('/').slice(-2, -1)[0];

          let seconds = convertToSeconds(lastLogin);
          let recentlyOnline = seconds <= 300;
          let h1 = document.querySelector("h1");

          const country = document.querySelector('div.block-profile > div.profile-list > div.margin-fix > div.column > div:nth-child(1) > em');
          const countryName = country.textContent.trim()
          let countryCode = contryCodesArray()[countryName] || [];
          const parent = document.querySelector('div.block-profile > div.profile-list > div.margin-fix > div.column > div:nth-child(1)');






function videoSearch(userVideosH2, uid, query) {
    let videosTotal = getRoundedTotalPages(userVideosH2);
    if (videosTotal !== null) {
        let resultArray = [];
        for (let pageInt = 1; pageInt <= videosTotal; pageInt++) {
            let nextFivePages = userProfileAsyncURL(uid, pageInt);
          // console.log(nextFivePages)
            fetchAndParseHTML(nextFivePages, function(htmlDoc) {
                let videos = htmlDoc.querySelectorAll('div#list_videos_uploaded_videos_items div.item');
                videos.forEach(video => {
                    let title = video.querySelector('a').getAttribute('title');
                    let url = video.querySelector('a').getAttribute('href');
                    let imgSrc = video.querySelector('img').getAttribute('data-original');
                    let duration = video.querySelector('.duration').textContent.trim();
                    let isPrivate = video.classList.contains('private');
                    if (title.includes(query)) {
                        resultArray.push({
                            private: isPrivate,
                            url: url,
                            imgSrc: imgSrc,
                            duration: duration
                        });
                    }
                });
            });
        }
        return resultArray;
    }
    return null;
}


// let search = videoSearch(userVideosH2, userId, "Becky");
// console.log(search)


function addButtonEventListener() {
    document.addEventListener('click', function(event) {
        var target = event.target;

        if (target && target.matches('a[data-action="ajax"]')) {
            const sessionStorageIndex = getCurrentUserVideoLocation();
            if (sessionStorageIndex) {
                // console.log("Session storage index found:", sessionStorageIndex);
                waitForSessionStorageChange();
            } else {
                console.log("Session storage index not found");
            }
        }
    });
}

function getCurrentUserVideoLocation() {
    let uid = currentUserID();
    let userVideoLocation = uid + ":https://www.camwhores.tv/members/" + userId + "/#list_videos_uploaded_videos:params";
    return sessionStorage.getItem(userVideoLocation);
}

function waitForSessionStorageChange() {
    // console.log("Waiting for session storage change");
    const initialSessionStorageValue = getCurrentUserVideoLocation();
    // console.log("Initial session storage value:", initialSessionStorageValue);
    const checkChangeInterval = setInterval(function() {
        const currentSessionStorageValue = getCurrentUserVideoLocation();
        // console.log("Current session storage value:", currentSessionStorageValue);
        if (currentSessionStorageValue !== initialSessionStorageValue) {
            // console.log("Session storage value changed");
            clearInterval(checkChangeInterval);
            updateVideoH2();
        }
    }, 50);
}




          if(recentlyOnline){
              h1.textContent += " (online)";
              h1.className = "online";
          }
          userDescription.textContent = userDescription.textContent.replace(/^[\s\t]+/, '');






          if (countryCode && countryName !== "no info") {
              country.remove();
              const img = document.createElement('img');
              img.src = `https://flagcdn.com/${countryCode}.svg`;
              img.width = 35;
              img.alt = countryName;
              img.title = countryName;
              img.style ="position:absolute;top: 50%;transform: translateY(-50%);left:4rem;"
              parent.appendChild(img);
              parent.style.position = "relative";
          }







            updateVideoH2()
            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 lastAutoFriend = localStorage.getItem('last_auto_friend');
          let userId = window.location.href.split('/').slice(-2, -1)[0];
          // console.log(userId)

          let retrievedData = JSON.parse(localStorage.getItem('last_cum_video_add'));
          let lastCumTitle = retrievedData.title;
          let lastVidCode = retrievedData.videoId;
          let lastUserID = retrievedData.userId;


          let pageTitle = document.title;
          let username = pageTitle.replace("'s Page", "");
          if (textarea !== null && !addButton.classList.contains('done') && username !== lastAutoFriend && lastCumTitle !== null && addButton !== null) {
              textarea.value = "";
              if(userId === lastUserID){
                textarea.value += friend_request_text + " " + lastCumTitle + "\n##" + lastVidCode;
              }
              document.querySelector('input[type="submit"].submit[value="Invite"]').click();
              localStorage.setItem('last_auto_friend', username);
              addButton.click(); // final submit button
              if(!document.hasFocus()){
                window.close();
              }

          }else if(!document.hasFocus() && addButton.classList.contains('done')){
              window.close();
          }
      }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');
              }
      }

            // console.log("document.hasFocus():",document.hasFocus())

  } // 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');
            let username = document.querySelector('.username a').textContent.trim();
            let userId = document.querySelector('.username a').getAttribute('href').split('/').slice(-2, -1)[0];
                  // console.log(userId)
            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 {
                        console.log("Not friends!");
                        var infoElement = null;
                        if(element1 !== null){
                          infoElement = element1
                        }else{
                          infoElement = element2
                        }
                        let headline = document.querySelector('body > div.container > div.content > div.headline > h1');
                        if (headline !== null) {
                            let title = headline.textContent.trim();
                            var currentUrl = window.location.href;
                            friendRequestSetup(title, currentUrl, userId);

                            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");
                        }

                      // Screenshots
                      document.querySelectorAll('.block-screenshots .item.private').forEach(function(el) {
                        let newEl = document.createElement('a');
                        newEl.innerHTML = el.innerHTML;
                        el.parentNode.replaceChild(newEl, el);

                        let img = newEl.querySelector('img');
                        if(!img) {
                          return;
                        }

                        img.src = img.getAttribute('data-original');
                        let srcThumb = img.getAttribute('data-original');
                        let srcBig = srcThumb.replace('/videos_screenshots/', '/videos_sources/').replace('/180x135/', '/screenshots/');

                        newEl.href = srcBig;
                        newEl.classList.add('item');
                        newEl.setAttribute('rel', 'screenshots');
                        newEl.setAttribute('data-fancybox-type', 'image');
                      });

                    } // END not friends
                })
                    .catch(error => console.error('Error fetching:', error));
            }



        }




if (window.location.href.startsWith("https://www.camwhores.tv/playlists/")) {
    console.log("Playlist!");

    let h1Element = document.querySelector('h1');
    let playlistItem = document.querySelector('#playlist_view_playlist_view_items a');
    let defaultTitle = playlistItem.querySelector('.title').textContent.trim();
    let defaultHref = playlistItem.href;

    h1Element.textContent = defaultTitle;

    let openVidButton = document.createElement('a');
    openVidButton.classList.add("button");
    openVidButton.textContent = "Open video";
    openVidButton.href = defaultHref;
    openVidButton.style.padding = "5px 5px 0 5px";
    h1Element.parentElement.appendChild(openVidButton);

    document.addEventListener('click', function(e) {
        let playlistItem = e.target.closest('#playlist_view_playlist_view_items a');
        if (playlistItem) {
            let videoTitle = playlistItem.querySelector('.title').textContent.trim();
            let videoHref = playlistItem.href;
            console.log("Clicked", videoTitle);
            h1Element.textContent = videoTitle;
            openVidButton.href = videoHref;
        }
    });

}



    } // end of (NOT "/my/videos/")

if (window.location.href === "https://www.camwhores.tv/my/") {
  // console.log("HELLO PROFILE")

  let profileCSS = document.createElement('style');
  profileCSS.className = "profile-css";
  profileCSS.textContent = `
  #edit_profile_about_me{
      height:225px;
  }
  strong.popup-title,
  span.selection [role="combobox"]{
      display:none;
  }
  body > div.fancybox-overlay.fancybox-overlay-fixed > div{
  top:0 !important;
      height: 100svh !important;
  }
  body > div.fancybox-overlay.fancybox-overlay-fixed,
  body > div.fancybox-overlay.fancybox-overlay-fixed > *{
    box-sizing: border-box;
  }
  div.fancybox-inner{
    height:100% !important;
    width: max-content !important;
  }
  .fancybox-close{
      top:9px !important;
  }
  `;
  document.head.appendChild(profileCSS);





}







// ANY PAGE



    function myVideosAsyncURL(pageInt){
      const utcTimestamp = new Date().getTime();
      const pageID = pageInt.toString();
      return "https://www.camwhores.tv/my/videos/?mode=async&function=get_block&block_id=list_videos_my_uploaded_videos&sort_by=&from_my_videos="+pageID+"&_="+utcTimestamp;
    }






 /*         fetchAndParseHTML("https://www.camwhores.tv/my/", function(htmlDoc) {
              console.log(htmlDoc)

        });*/




    function pagesLastProcessedVideo(page, callback) {
        fetchAndParseHTML(myVideosAsyncURL(page), function(htmlDoc) {
            const videoItems = htmlDoc.querySelectorAll("#list_videos_my_uploaded_videos_items > form > div.item.private");
            let lastProcessingIndex = -1;

            for (let i = videoItems.length - 1; i >= 0; i--) {
                if (videoItems[i].classList.contains('processing')) {
                    lastProcessingIndex = i;
                    break;
                }
            }

            if (lastProcessingIndex !== -1 && lastProcessingIndex < videoItems.length - 1) {
                const precedingItem = videoItems[lastProcessingIndex + 1];
                const checkbox = precedingItem.querySelector(".item-control-holder .toggle-button input[type='checkbox']");
                if (checkbox) {
                    callback(checkbox.value);
                    return;
                }
            }

            callback(false);
        });
    }


    function lastProcessedVideoID(callback) {
        var found = false;
        var completedIterations = 0;
        let maxPages = 3;

        for (var pageN = 1; pageN <= maxPages; pageN++) {
            (function(page) {
                pagesLastProcessedVideo(page, function(checkboxValue) {
                    completedIterations++; // Increment the counter for each completed iteration

                    if (checkboxValue && !found) {
                        found = true;
                        callback(checkboxValue);
                    } else if (completedIterations === maxPages && !found) { // Check if all iterations have completed and no checkbox value is found
                        callback(false);
                    }
                });
            })(pageN);
        }
    }

    function loadLastVideoData() {
        var jsonData = localStorage.getItem('lastVideoData');
        if (!jsonData) {
            return [null, null]; // No stored data, return null values
        }

        var data = JSON.parse(jsonData);
        return data;
    }

    function lastVideoDataAge(refreshMinutes=30) {
        var data = loadLastVideoData();
        if (!data[1]) { // Timestamp
            console.log("Force recheck")
            var bigTime = (refreshMinutes * 60) + 1;
            // bigTime = 0;
            return bigTime; // No stored timestamp, assume age is 0 seconds
        }

        var timestamp = data[1];
        var currentTime = Date.now();
        var elapsedTimeSeconds = (currentTime - timestamp) / 1000;

        return elapsedTimeSeconds;
    }

    function saveLastVideoID(callback) {
        const lastID = loadLastVideoData()[0];
        lastProcessedVideoID(function(currentID) {
            var timestamp = Date.now();
            var data = [currentID, timestamp]; // Include lastID and currentID in the data array
            var jsonData = JSON.stringify(data);
            localStorage.setItem('lastVideoData', jsonData);
            callback(lastID, currentID); // Invoke the callback with both lastID and currentID
            console.log("Last ID:", lastID, "\nCurrent ID:", currentID, "(https://www.camwhores.tv/edit-video/"+currentID+"/)");
        });
    }

    function alertNewVideo(newID){
        let text = "A new video of yours has been published.\nGo to My Videos?";
        let url = "/my/videos/";

        if (confirm(text)) {
            window.location.href = url;
        }
    }
    function updateLastVideoData(minutes = 30){
        const waitTime = minutes * 60;
        let ageOfCheck = lastVideoDataAge(refreshVideosMinutes);
        // let ageOfCheck = 31*60;
        // console.log("seconds passed:",ageOfCheck,"\nwaitTime:",waitTime,"\n")
        let minutesOfAge = Math.round(ageOfCheck / 60);
        if(ageOfCheck > waitTime){
            saveLastVideoID(function(lastID, newID) {
                // console.log("lastID:",lastID,"\nnewID:",newID)
                if(newID && lastID && lastID !== newID){
                    alertNewVideo(newID);
                }else{
                  console.log("No new videos were published")
                  // console.log("Still the same video ("+lastID,"==",newID+")")
                }
            });
        } else {
            console.log("Only", minutesOfAge, "minutes have passed,",(minutes - minutesOfAge), "to go");
        }
    }



      // console.log("notifyProcessedVideos:",notifyProcessedVideos)
    if(notifyProcessedVideos){
        updateLastVideoData(refreshVideosMinutes);
    }










  function contryCodesArray(){
    return {
    "Andorra": "ad",
    "United Arab Emirates": "ae",
    "Afghanistan": "af",
    "Antigua and Barbuda": "ag",
    "Anguilla": "ai",
    "Albania": "al",
    "Armenia": "am",
    "Angola": "ao",
    "Antarctica": "aq",
    "Argentina": "ar",
    "American Samoa": "as",
    "Austria": "at",
    "Australia": "au",
    "Aruba": "aw",
    "Åland Islands": "ax",
    "Azerbaijan": "az",
    "Bosnia and Herzegovina": "ba",
    "Barbados": "bb",
    "Bangladesh": "bd",
    "Belgium": "be",
    "Burkina Faso": "bf",
    "Bulgaria": "bg",
    "Bahrain": "bh",
    "Burundi": "bi",
    "Benin": "bj",
    "Saint Barthélemy": "bl",
    "Bermuda": "bm",
    "Brunei": "bn",
    "Bolivia": "bo",
    "Caribbean Netherlands": "bq",
    "Brazil": "br",
    "Bahamas": "bs",
    "Bhutan": "bt",
    "Bouvet Island": "bv",
    "Botswana": "bw",
    "Belarus": "by",
    "Belize": "bz",
    "Canada": "ca",
    "Cocos (Keeling) Islands": "cc",
    "DR Congo": "cd",
    "Central African Republic": "cf",
    "Republic of the Congo": "cg",
    "Switzerland": "ch",
    "Côte d'Ivoire (Ivory Coast)": "ci",
    "Cook Islands": "ck",
    "Chile": "cl",
    "Cameroon": "cm",
    "China": "cn",
    "Colombia": "co",
    "Costa Rica": "cr",
    "Cuba": "cu",
    "Cape Verde": "cv",
    "Curaçao": "cw",
    "Christmas Island": "cx",
    "Cyprus": "cy",
    "Czechia": "cz",
    "Germany": "de",
    "Djibouti": "dj",
    "Denmark": "dk",
    "Dominica": "dm",
    "Dominican Republic": "do",
    "Algeria": "dz",
    "Ecuador": "ec",
    "Estonia": "ee",
    "Egypt": "eg",
    "Western Sahara": "eh",
    "Eritrea": "er",
    "Spain": "es",
    "Ethiopia": "et",
    "European Union": "eu",
    "Finland": "fi",
    "Fiji": "fj",
    "Falkland Islands": "fk",
    "Micronesia": "fm",
    "Faroe Islands": "fo",
    "France": "fr",
    "Gabon": "ga",
    "United Kingdom": "gb",
    "England": "gb-eng",
    "Northern Ireland": "gb-nir",
    "Scotland": "gb-sct",
    "Wales": "gb-wls",
    "Grenada": "gd",
    "Georgia": "ge",
    "French Guiana": "gf",
    "Guernsey": "gg",
    "Ghana": "gh",
    "Gibraltar": "gi",
    "Greenland": "gl",
    "Gambia": "gm",
    "Guinea": "gn",
    "Guadeloupe": "gp",
    "Equatorial Guinea": "gq",
    "Greece": "gr",
    "South Georgia": "gs",
    "Guatemala": "gt",
    "Guam": "gu",
    "Guinea-Bissau": "gw",
    "Guyana": "gy",
    "Hong Kong": "hk",
    "Heard Island and McDonald Islands": "hm",
    "Honduras": "hn",
    "Croatia": "hr",
    "Haiti": "ht",
    "Hungary": "hu",
    "Indonesia": "id",
    "Ireland": "ie",
    "Israel": "il",
    "Isle of Man": "im",
    "India": "in",
    "British Indian Ocean Territory": "io",
    "Iraq": "iq",
    "Iran": "ir",
    "Iceland": "is",
    "Italy": "it",
    "Jersey": "je",
    "Jamaica": "jm",
    "Jordan": "jo",
    "Japan": "jp",
    "Kenya": "ke",
    "Kyrgyzstan": "kg",
    "Cambodia": "kh",
    "Kiribati": "ki",
    "Comoros": "km",
    "Saint Kitts and Nevis": "kn",
    "North Korea": "kp",
    "South Korea": "kr",
    "Kuwait": "kw",
    "Cayman Islands": "ky",
    "Kazakhstan": "kz",
    "Laos": "la",
    "Lebanon": "lb",
    "Saint Lucia": "lc",
    "Liechtenstein": "li",
    "Sri Lanka": "lk",
    "Liberia": "lr",
    "Lesotho": "ls",
    "Lithuania": "lt",
    "Luxembourg": "lu",
    "Latvia": "lv",
    "Libya": "ly",
    "Morocco": "ma",
    "Monaco": "mc",
    "Moldova": "md",
    "Montenegro": "me",
    "Saint Martin": "mf",
    "Madagascar": "mg",
    "Marshall Islands": "mh",
    "North Macedonia": "mk",
    "Mali": "ml",
    "Myanmar": "mm",
    "Mongolia": "mn",
    "Macau": "mo",
    "Northern Mariana Islands": "mp",
    "Martinique": "mq",
    "Mauritania": "mr",
    "Montserrat": "ms",
    "Malta": "mt",
    "Mauritius": "mu",
    "Maldives": "mv",
    "Malawi": "mw",
    "Mexico": "mx",
    "Malaysia": "my",
    "Mozambique": "mz",
    "Namibia": "na",
    "New Caledonia": "nc",
    "Niger": "ne",
    "Norfolk Island": "nf",
    "Nigeria": "ng",
    "Nicaragua": "ni",
    "Netherlands": "nl",
    "Norway": "no",
    "Nepal": "np",
    "Nauru": "nr",
    "Niue": "nu",
    "New Zealand": "nz",
    "Oman": "om",
    "Panama": "pa",
    "Peru": "pe",
    "French Polynesia": "pf",
    "Papua New Guinea": "pg",
    "Philippines": "ph",
    "Pakistan": "pk",
    "Poland": "pl",
    "Saint Pierre and Miquelon": "pm",
    "Pitcairn Islands": "pn",
    "Puerto Rico": "pr",
    "Palestine": "ps",
    "Portugal": "pt",
    "Palau": "pw",
    "Paraguay": "py",
    "Qatar": "qa",
    "Réunion": "re",
    "Romania": "ro",
    "Serbia": "rs",
    "Russia": "ru",
    "Rwanda": "rw",
    "Saudi Arabia": "sa",
    "Solomon Islands": "sb",
    "Seychelles": "sc",
    "Sudan": "sd",
    "Sweden": "se",
    "Singapore": "sg",
    "Saint Helena, Ascension and Tristan da Cunha": "sh",
    "Slovenia": "si",
    "Svalbard and Jan Mayen": "sj",
    "Slovakia": "sk",
    "Sierra Leone": "sl",
    "San Marino": "sm",
    "Senegal": "sn",
    "Somalia": "so",
    "Suriname": "sr",
    "South Sudan": "ss",
    "São Tomé and Príncipe": "st",
    "El Salvador": "sv",
    "Sint Maarten": "sx",
    "Syria": "sy",
    "Eswatini (Swaziland)": "sz",
    "Turks and Caicos Islands": "tc",
    "Chad": "td",
    "French Southern and Antarctic Lands": "tf",
    "Togo": "tg",
    "Thailand": "th",
    "Tajikistan": "tj",
    "Tokelau": "tk",
    "Timor-Leste": "tl",
    "Turkmenistan": "tm",
    "Tunisia": "tn",
    "Tonga": "to",
    "Turkey": "tr",
    "Trinidad and Tobago": "tt",
    "Tuvalu": "tv",
    "Taiwan": "tw",
    "Tanzania": "tz",
    "Ukraine": "ua",
    "Uganda": "ug",
    "United States Minor Outlying Islands": "um",
    "United Nations": "un",
    "United States": "us",
    "Uruguay": "uy",
    "Uzbekistan": "uz",
    "Vatican City (Holy See)": "va",
    "Saint Vincent and the Grenadines": "vc",
    "Venezuela": "ve",
    "British Virgin Islands": "vg",
    "United States Virgin Islands": "vi",
    "Vietnam": "vn",
    "Vanuatu": "vu",
    "Wallis and Futuna": "wf",
    "Samoa": "ws",
    "Kosovo": "xk",
    "Yemen": "ye",
    "Mayotte": "yt",
    "South Africa": "za",
    "Zambia": "zm",
    "Zimbabwe": "zw"}

  }



})();