Sleazy Fork is available in English.

Camwhores.tv Utilities Mod

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

Verze ze dne 26. 07. 2024. Zobrazit nejnovější verzi.

// ==UserScript==
// @name         Camwhores.tv Utilities Mod
// @namespace    https://sleazyfork.org/users/1281730-vipprograms
// @version      1.12.0
// @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        GM_download
// @grant        GM_openInTab
// @grant        window.close
// @icon         data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAMUExURQAAAP8ANwwA/////7gbQJkAAAABdFJOUwBA5thmAAAAAWJLR0QDEQxM8gAAAAd0SU1FB+gDHhIuCjXV/h8AAAA4SURBVAjXY2ANDQ1gEA0NDWEIYWBgZAhgAAIUghEiC1YHBhpMDRpIhBbXghUMXKtWLWBgWqHVAACjlwz/pN0YPwAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyNC0wMy0zMFQxODo0NjowOSswMDowME+iXNIAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjQtMDMtMzBUMTg6NDY6MDkrMDA6MDA+/+RuAAAAKHRFWHRkYXRlOnRpbWVzdGFtcAAyMDI0LTAzLTMwVDE4OjQ2OjEwKzAwOjAwMNiA/AAAAABJRU5ErkJggg==
// @require      https://cdn.jsdelivr.net/npm/@violentmonkey/shortcut@1
// @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;

    const { register } = VM.shortcut;
    const currentVersion = GM_info.script.version;
    const currentDate = new Date();
    const metaPage = "https://update.sleazyfork.org/scripts/491272/Camwhorestv%20Utilities%20Mod.meta.js";

    VM.shortcut.register('c-i', () => {
      console.log('You just pressed Ctrl-I');
    });


    function isArrayEmpty(arr) {
        return arr.length === 0;
    }
    function retrieveValueFromStorage(key) {
        // If value/index NOT present, returns undefined
        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 saveOption(optionName, currentValue){
        let options = retrieveValueFromStorage("options") || {};
        options[optionName] = currentValue;
        saveValue("options", options);
    }


    function toggleChange(optionName, currentValue = false){ // ONLY for menu commands
        var updatedOptions;
        let options = retrieveValueFromStorage("options");
        var currentState = options[optionName] !== undefined ? options[optionName] : currentValue;

        _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] = currentValue;
            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:";
    const alternative_thumbnails_users = ['deathstar45','usualsuspekt','MrPussyGod','peacebitch','ADCGHN11123'];

    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",
      alternative_thumbnails_users: "users with bad default thumbnails"
    }
    optionsArrayEditor("auto_replies", optionsKeyLegible)
    optionsArrayEditor("highlight_keywords", optionsKeyLegible)
    optionsStringEditor("friend_request_text", optionsKeyLegible)


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

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

    let updateRemindersOptionName = "update reminders";
    toggleChange(updateRemindersOptionName, true)
    var updateReminders = retrieveValueFromStorage("options")[updateRemindersOptionName];



    const style = document.createElement('style');
  // custom CSS
    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;
}
div.block-profile > div > div > div.about-me > div{
    width: 100%;
    box-sizing: border-box;
}
div.block-profile > div > div > div.about-me > div>em{
width: 100%;
    display: inline-block;
    word-break: auto-phrase;
    word-wrap: break-word;
    box-sizing: border-box;
    text-wrap: pretty;
}

.user-search {
    float: right;
    /*min-width: 140px;*/
    position: relative;
    margin-left: 3px;
    cursor: pointer;
    background: #f1f1f1;
    background: linear-gradient(to bottom, #f1f1f1 0%, #d8d8d8 100%);
    border-radius: 2px;
    padding:0;
}
.user-search strong {
    display: block;
    font-size: 12px;
    line-height: 15px;
    padding: 5px 12px 5px 28px;
    white-space: nowrap;
    color: #4e4e4e;
    cursor: pointer;
    max-width: 200px;
    overflow: hidden;
}
.user-search .type-search {
    background: url('https://shrph.altervista.org/img/search.png') 5px 4px no-repeat;
}
.user-search .icon {
    display: block;
    position: absolute;
    width: 100%;
    height: 100%;
    top:0;
}
#tab_screenshots > div > .item,
#tab_screenshots > div > .item > .img {
    width: 250px;
    height: auto;
}

#tab_screenshots > div > .item > .img {
}
@keyframes fadeAnimation {
    0% { opacity: 1; }
    50% { opacity: .3; }
    100% { opacity: 1; }
}

.fade {
    animation: fadeAnimation 1s infinite;
}
.switch {
  position: relative;
  display: inline-block;
  width: 30px;
  height: 17px;
}

.switch input {
  opacity: 0;
  width: 0;
  height: 0;
}

.slider {
  position: absolute;
  cursor: pointer;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: #ccc;
  -webkit-transition: .4s;
  transition: .4s;
}

.slider:before {
  position: absolute;
  content: "";
  height: 13px;
  width: 13px;
  left: 2px;
  bottom: 2px;
  background-color: white;
  -webkit-transition: .4s;
  transition: .4s;
}

input:checked + .slider {
  background-color: #f56c08;
}

input:focus + .slider {
  box-shadow: 0 0 1px #F28022;
}

input:checked + .slider:before {
  -webkit-transform: translateX(13px);
  transform: translateX(13px);
}

.slider.round {
  border-radius: 17px;
}

.slider.round:before {
  border-radius: 50%;
}

.list-comments .dim-comment p {
  opacity: 1;
}
.list-comments .dim-comment {
  background-color: #9e1e1e2b;
  background-image: none;
}
`;
    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
    };

    let lastCumVideoAdd = JSON.parse(localStorage.getItem('last_cum_video_data')) || {};
    lastCumVideoAdd[userID] = cumData;
    localStorage.setItem('last_cum_video_data', JSON.stringify(lastCumVideoAdd));

  }

       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:",paramsValue)
    if(!paramsValue){
      return 1;
    }
    let int = parseInt(paramsValue, 10);
  // console.log(int)
    return int;
}

function setUploadButtonTimestamp(){
    var timestamp = Date.now();
    var jsonData = JSON.stringify(timestamp);
    localStorage.setItem('UploadButtonTimestamp', jsonData);
}



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 secondsSinceLocalStorage(name) {
    let storedItem = JSON.parse(localStorage.getItem(name));
    if (storedItem) {
        let currentTime = Date.now();
        let storedTime = storedItem.timestamp;
        return (currentTime - storedTime) / 1000; // Time difference in seconds
    } else {
        return null;
    }
}


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

function secondsSinceTimestamp(timestamp){
    return (Date.now() - timestamp) / 1000;
}


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

silentUidUpdater()


function uploadRestored(){
  alert("The upload button has been restored!")
  localStorage.removeItem("UploadButtonTimestamp");
}
// UPLOAD button
const nav = document.querySelector('.navigation .primary');
let lastCheck = localStorage.getItem("UploadButtonTimestamp"); // EXAMPLE: "1717655623061"
let minutesSinceLastCheck = secondsSinceTimestamp(lastCheck) / 60;
let roundedMinutes = Math.floor(minutesSinceLastCheck);
if (nav && restoreUploadButton && ![...nav.querySelectorAll('a')].some(link => link.textContent.trim().includes('Upload'))) {
    const uploadLink = document.createElement('a');
    uploadLink.style.backgroundColor = '#215521';
    uploadLink.style.display = 'block';
    uploadLink.style.padding = '11px 0';
    uploadLink.style.cursor = 'pointer';
    uploadLink.textContent = 'UPLOAD';
    uploadLink.href = '/upload-video/';
    nav.appendChild(uploadLink);

    let uploadURL = '/upload-video/'; //'https://www.camwhores.tv/upload-video/'
    uploadLink.addEventListener('click', function(event) {
        event.preventDefault();
        getResponseStatus(uploadURL).then(status => {
            if (status === 200) {
                window.location.href = uploadURL;
            } else {
                if (confirm("Upload functionality is currently fully disabled\n(" + status.toString() + ")\nDo you want to be notified when it's available again?")) {
                    setUploadButtonTimestamp();
                }
            }
        });
    });

    if(lastCheck && minutesSinceLastCheck > 30){
          getResponseStatus(uploadURL).then(status => {
              if (status === 200) {
                  uplaodRestored();
              } else {
                  console.log("Upload button still unavailable. Last check",minutesSinceLastCheck,"minutes ago")
                  setUploadButtonTimestamp();
              }
          });
    }else{
        // console.log("Only",roundedMinutes, "minutes have passed since last upload button check,", 30 - roundedMinutes, "to go");
    }


}else{
  // console.log("Couldn't/shouldn't restoreUploadButton", restoreUploadButton)
  if(lastCheck){
      uploadRestored()
  }
}

     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(3))






    function messagePageInfo(pageN) {
      let urlToPage = myMessagesAsyncURL(pageN);
      // 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 hasUnreadMessage(currentPage) {
          const data = await messagePageInfo(currentPage);
          return data.some(message => message.unread);
      }

      async function delay(ms) {
          return new Promise(resolve => setTimeout(resolve, ms));
      }

      async function lastUnreadPage() {
          let currentPage = 1;
          let hasUnread = true;
          while (hasUnread) {
              const data = await messagePageInfo(currentPage);
              hasUnread = data.some(message => message.unread);
              if (!hasUnread) break;
              currentPage++;
              await delay(75);
          }
          return currentPage - 1;
      }




async function checkAndFixMessages() {
  const currentPage = getCurrentPage();
  const data = await messagePageInfo(currentPage);
  // console.log(data);

  let hasNewElements = false;

  data.forEach(item => {
    const userItem = document.querySelector(`#list_members_my_conversations_items > div.item > a[title="${item.name}"]`);
    if (userItem) {
      const unreadNotification = userItem.querySelector('div.img .unread-notification');
      if (unreadNotification && !item.unread) {
        unreadNotification.remove();
        console.log("Message with", item.name, "was read");
      }
    } else{
      hasNewElements = true;
    }
  });

  if (hasNewElements) {
    location.reload();
  }
}









        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 + '"]');
                  // console.log("usernameLink:",usernameLink)
                    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()
            silentUidUpdater()
            checkAndFixMessages()
        }, 5000);

        setInterval(function() {
            addButtons()
        }, 500);


    function addButtons() {
        const h2Element = document.querySelector('#list_members_my_conversations .headline h2');
        if (!h2Element) return console.log('h2Element not found');

        if (!document.getElementById('refreshIcon')) {
            const refreshIcon = document.createElement('span');
            refreshIcon.id = 'refreshIcon';
            refreshIcon.innerHTML = '&#8635;';
            refreshIcon.title = 'Refresh Utilities Mod';
            refreshIcon.style = 'cursor:pointer;margin-left:10px;';
            refreshIcon.addEventListener('click', () => {
                processThumbnails();
                console.log('Refreshing...');
            });
            h2Element.appendChild(refreshIcon);
        }

        if (!document.getElementById('lastUnreadButton')) {
            const lastUnreadButton = document.createElement('a');
            lastUnreadButton.id = 'lastUnreadButton';
            lastUnreadButton.innerHTML = '⏭';
            lastUnreadButton.title = 'Go to oldest unread message';
            lastUnreadButton.style = 'cursor:pointer;margin-left:10px;text-decoration:none;';
            lastUnreadButton.addEventListener('click', async () => {
                lastUnreadButton.classList.add('fade');
                const oldestUnreadPage = await lastUnreadPage();
                console.log(oldestUnreadPage);
                const linkElement = document.querySelector(`a[href="/my/messages/${oldestUnreadPage}/"][data-block-id="list_members_my_conversations"]`);
                if (linkElement) {
                    linkElement.click();
                } else {
                    console.log(`Element for page ${oldestUnreadPage} not found`);
                }
                lastUnreadButton.classList.remove('fade');

            });
            h2Element.appendChild(lastUnreadButton);
        }
    }

    addButtons()



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

        // VM.shortcut.register('c-enter', () => {
        //   console.log('You just pressed Ctrl-I');
        // });


        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)
         if (sessionStorage.getItem('continue') === 'true') {
                sessionStorage.removeItem('continue');
                if (history.length === 1) {
                    window.location.href = "https://www.camwhores.tv/members/"+userID+"/#list_videos_my_uploaded_videos";
                }
          }

        if (confirmButton){
            confirmButton.addEventListener('click', function() {
                sessionStorage.setItem('continue', 'true');
            });
        }

        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) {
    const twoYearsSeconds = 60 * 60 * 24 * 365 * 2;
    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 secondsSinceOnline = convertToSeconds(lastLogin);
    let recentlyOnline = secondsSinceOnline <= 300;
    // let recentlyOnline = true;
    const headlineH2 = document.querySelector('#list_messages_my_conversation_messages .headline h2');
    console.log("recentlyOnline:", recentlyOnline);
    var recentlyUploaded = false;
    console.log("Has focus:",document.hasFocus(),"titleText:",titleText)
    if(!document.hasFocus() && !titleText){
      denyClose.click()
      window.close();
    }

    if(lastUploadTime){
      let lastUploadTimeSeconds = convertToSeconds(lastUploadTime);
      recentlyUploaded = lastUploadTimeSeconds < twoYearsSeconds;
    }

    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

            if(recentlyUploaded){
                updateButtonStyle(confirmButton, true);
                updateButtonStyle(confirmClose, true);
            }else{
                updateButtonStyle(rejectButton, false);
                updateButtonStyle(denyClose, false);
            }

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


              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+"?please_check_friend"; // 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);
            if (!response.ok) {
                console.error('Error loading video page:', response.status);
                return { byFriend: false, usernameID: null };
            }

            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;
            // let username = doc.querySelector("#tab_video_info > div > div.block-user > div.username").textContent.trim();
            let usernameBlock = doc.querySelector("#tab_video_info > div > div.block-user > div.username > a") || doc.querySelector("#tab_album_info > div > div.block-user > div > a");
            // console.log(usernameBlock)
            let username = usernameBlock?.textContent.trim();

            var vid_code = userURL.replace("https://www.camwhores.tv/members/", "");
            var usernameID = vid_code.split("/")[0];

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

        function moveToAltThumb(image) {
                const src = image.getAttribute('src');
                const newSrc = src.replace('1.jpg', '5.jpg');
                if (src && src.endsWith('1.jpg')) {
                    image.setAttribute('src', newSrc);
                }
        }


        async function applyStyleToPrivateVideos() {
            const privateVideos = addPrivateVideos();
            for (const video of privateVideos) {
                let imgElement = video.querySelector('div > img');

                let videoLink = video.getAttribute('href');
                let videoTitle = video.querySelector('strong.title').textContent.trim();
                let { byFriend: hasElement, usernameID, username } = await checkVideoPage(videoLink);
                // console.log(videoLink, "is by:", username)
                // 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';
                    }
                    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"
                    }
                }
                     if (alternative_thumbnails_users.includes(username)) {
                      moveToAltThumb(imgElement);
                      // console.log(username, "IS in",alternative_thumbnails_users)

                    }else{
                      // console.log(username, "not in",alternative_thumbnails_users)
                    }

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


        setInterval(() => {
            applyStyleToPrivateVideos();
            findRelevantKeywords()
        }, 500);



        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 secondsSinceOnline = convertToSeconds(lastLogin);
          let recentlyOnline = secondsSinceOnline <= 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 addSearchButton(){
          let sortElement = document.querySelector("#list_videos_uploaded_videos > div.headline > div.sort");
          if(sortElement){
              let searchButton = document.createElement('div');

              let span = document.createElement('span');
              span.classList.add('icon', 'type-search');

              let strong = document.createElement('strong');
              strong.textContent = 'Search videos';

              searchButton.classList.add('user-search');
              searchButton.appendChild(strong);
              searchButton.appendChild(span);

              sortElement.parentNode.insertBefore(searchButton, sortElement);

              searchButton.addEventListener('click', searchDialog);
          }
  }

addSearchButton()



function searchDialog() {
  let dialog = document.createElement('div');
  dialog.id = "search-dialog";
  dialog.style.position = 'fixed';
  dialog.style.top = '50%';
  dialog.style.left = '50%';
  dialog.style.transform = 'translate(-50%, -50%)';
  dialog.style.backdropFilter = 'blur(5px)';
  dialog.style.backgroundColor = 'rgb(0 0 0 / 44%)';
  dialog.style.padding = '20px';
  dialog.style.borderRadius = '10px';

  dialog.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.1)';
  dialog.style.zIndex = '1000';

  let form = document.createElement('form');
  form.style = "padding: 10px 10px 0 0"

  let input = document.createElement('input');
  input.type = 'text';
  input.autofocus = true;
  input.placeholder = 'Search...';
  input.style.marginRight = '5px';
  input.style.padding = '5px';
  input.placeholder = 'blowjob';

  let submitButton = document.createElement('button');
  submitButton.type = 'submit';
  submitButton.style = 'padding: 5px;box-sizing: border-box;height: 30px;cursor:pointer;';
  submitButton.textContent = 'Search';

  let highlightsSearch = document.createElement('button');
  highlightsSearch.type = 'button';
  highlightsSearch.style = 'display:block;padding:5px;box-sizing:border-box;height:30px;cursor:pointer;width:100%;margin-top:5px';
  highlightsSearch.title = "Search", highlight_keywords.join(", ");
  highlightsSearch.textContent = 'Any highlight';

  let closeBtn = document.createElement('div');
  closeBtn.type = 'div';
  closeBtn.style = 'position:absolute;top:5px;right:5px;';
  closeBtn.classList.add('fancybox-item', 'fancybox-close');




  form.appendChild(input);
  form.appendChild(submitButton);
  form.appendChild(highlightsSearch);
  form.appendChild(closeBtn);
  dialog.appendChild(form);
  document.body.appendChild(dialog);



  form.addEventListener('submit', function(event) {
      event.preventDefault();
      if(input.value && input.value !== ""){
          displayResults(input.value);
      }
      document.body.removeChild(dialog);
  });

  highlightsSearch.addEventListener('click', function(event) {
    event.preventDefault();
    displayResults("");
    document.body.removeChild(dialog);
  });

  closeBtn.addEventListener('click', function(event) {
    event.preventDefault();
    document.body.removeChild(dialog);
  });


}

async function displayResults(input) {
    try {
        const resultList = document.createElement('div');
        resultList.id = 'cum_search_results';
        resultList.classList = "list-videos";

        // Create a container div for the loading image
        const loadingContainer = document.createElement('div');
        loadingContainer.style.textAlign = 'center'; // Center horizontally
        const loadingImage = document.createElement('img');
        loadingImage.src = "https://samherbert.net/svg-loaders/svg-loaders/three-dots.svg";
        loadingImage.alt = "Loading...";
        loadingImage.style.width = "50px";
        loadingImage.style.height = "50px";
        loadingContainer.appendChild(loadingImage);
        document.querySelector("#list_videos_uploaded_videos").appendChild(loadingContainer);

        const resultObject = await videoSearch(userVideosH2, userId, input);
        loadingContainer.remove(); // Remove the loading image container

        resultList.innerHTML = `
            <div class="headline" style="padding: 15px 5px 7px 5px;">
                <h2>Search results</h2>
            </div>`;

        if (!resultObject || Object.keys(resultObject).length === 0) {
            resultList.textContent = "No results found";
        } else {
            const boxDiv = document.createElement('div');
            boxDiv.classList.add('box');
            for (const video of Object.values(resultObject)) {
                const { url, imgSrc, duration, title } = video;
                const videoDiv = document.createElement('div');
                videoDiv.classList.add('item');
                videoDiv.style.marginLeft = "11px";
                videoDiv.innerHTML = `
                    <a href="${url}" title="${title}">
                        <div class="img">
                            <img class="thumb lazy-load" src="${imgSrc}" alt="${title}" width="180" height="135" style="display: block;">
                        </div>
                        <strong class="title">${title}</strong>
                        <div class="wrap">
                            <div class="duration">${duration}</div>
                        </div>
                    </a>`;
                boxDiv.appendChild(videoDiv);
            }
            resultList.appendChild(boxDiv);
        }

        const listContainer = document.querySelector("#list_videos_uploaded_videos");
        const existingResult = document.querySelector("#cum_search_results");
        existingResult ? existingResult.replaceWith(resultList) : listContainer.insertAdjacentElement('afterend', resultList);
    } catch (error) {
        console.error("Error:", error);
    }
}


















async function videoSearch(userVideosH2, uid, query) {
    let totalVideoPages = getRoundedTotalPages(userVideosH2);
    let approxTotalVideos = totalVideoPages * 5;
    let timeout = approxTotalVideos > 500 ? approxTotalVideos / 5 : 75;
    let searchTerms = query ? [query.toLowerCase()] : highlight_keywords.map(k => k.toLowerCase());

    if (totalVideoPages !== null) {
        let resultArray = [];
        let fetchPromises = [];

        for (let pageInt = 1; pageInt <= totalVideoPages; pageInt++) {
            let nextFivePages = userProfileAsyncURL(uid, pageInt);
            let fetchPromise = new Promise((resolve) => {
                setTimeout(() => {
                    fetchAndParseHTML(nextFivePages, (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');
                            let lowerTitle = title.toLowerCase();
                            if (searchTerms.some(term => lowerTitle.includes(term))) {
                                resultArray.push({ title, private: isPrivate, url, imgSrc, duration });
                            }
                        });
                        resolve();
                    });
                }, timeout * (pageInt - 1));
            });
            fetchPromises.push(fetchPromise);
        }

        await Promise.all(fetchPromises);
        return resultArray;
    } else {
        console.log("ERROR in totalVideoPages:", totalVideoPages);
        return null;
    }
}







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();
            addSearchButton();
        }
    }, 50);
}




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






          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")) {
          var userVideoData,lastCumTitle,lastVidCode,lastUserID;
          let addButton = document.querySelector('a[href="#friends"][data-action="add_to_friends"]');
          let textarea = document.getElementById('add_to_friends_message');
          let lastAutoFriend = localStorage.getItem('last_auto_friend');
          let userId = window.location.href.split('/').slice(-2, -1)[0];
          let confirmButton = document.querySelector('input[name="confirm"]');


          let retrievedData = JSON.parse(localStorage.getItem('last_cum_video_data')) || {};
          if (retrievedData[userId]) {
              userVideoData = retrievedData[userId];
              console.log(userVideoData);
              lastCumTitle = userVideoData.title;
              lastVidCode = userVideoData.videoId;
              lastUserID = userVideoData.userId;
          } else {
              console.log("No data found for this user.");
          }


          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
          }
          // console.log(confirmButton)
          if(confirmButton) confirmButton.click();



          if (history.length === 1) {
              window.close();
          }
        // console.log("Should add?")
      }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');
              }
          if (history.length === 1) {
              window.close();
          }
      }


            // console.log("document.hasFocus():",document.hasFocus())
// Wait for the whole document, including stylesheets and images, to be loaded
window.addEventListener('load', function() {
  // console.log("loaded")
    setTimeout(function() {
  // console.log("timeouted")
        if (window.location.href.includes('#list_videos_my_uploaded_videos')) {
            console.log("scroll!");

            const element = document.querySelector("#list_videos_uploaded_videos > div.headline");
            if (element) {
                element.scrollIntoView({ behavior: 'smooth' });
            }
        }
    }, 2000); // Adjust the delay as needed
});



  } // 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 if(window.location.href.includes("please_check_friend")){

                        (element1 || element2).innerHTML += "<br><br>Friendship confirmed? Reloading in 4 seconds";
                        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));
            }




function waitForElementExists(parent, selector) {
        return new Promise((resolve, reject) => {
            const observer = new MutationObserver((mutations, me) => {
                const element = parent.querySelector(selector);
                if (element) {
                    resolve(element);
                    me.disconnect();
                }
            });

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

function addDownloadLink(video) {
    const url = video.getAttribute('src');
    const name = document.querySelector('.headline').innerText + '.mp4';

    // Check if the download link already exists
    if (document.getElementById('downloadVideoLink')) return;

    // Create the download link
    const link = document.createElement('a');
    link.id = 'downloadVideoLink';
    link.innerText = 'Download';
    link.href = url;
    link.download = name;
    link.classList = "toggle-button";

    const li = document.createElement('li');
    li.appendChild(link);

    const ul = document.querySelector('div.video-holder > div.video-info > div > div.info-buttons > div.tabs-menu > ul');
    ul.insertBefore(li, ul.firstChild);
}


    waitForElementExists(document.body, 'video')
        .then(video => addDownloadLink(video))
        .catch(error => console.error('Error:', error));



function waitForVideoDuration(maxAttempts, intervalMs) {
  var attempts = 0;

  // Approximated percentages
  var percentages = [/* 0:14, */ 25, 40, 59.75, 79]; // CONSIDER 0:14 IN FRONT IF EVERYTHING! (15:49)

  function checkDuration() {
    var player = flowplayer();
    if (player && player.video && typeof player.video.duration === 'number') {
      var videoDuration = player.video.duration;

      // Calculate percentages based on approximations
      var calculatedPercentages = percentages.map(function(percent) {
        return (percent / 100) * videoDuration;
      });

      console.log("Video Duration:", videoDuration);
      console.log("Calculated Percentages:", calculatedPercentages);

      // Determine the first timestamp as the minimum between 14 seconds and 5% of video duration
      var firstTimestamp = 14;

      // Check if #tab_screenshots exists
      var tabScreenshots = document.getElementById('tab_screenshots');
      if (!tabScreenshots) {
        tabScreenshots = document.createElement('div');
        tabScreenshots.id = 'tab_screenshots';
        document.body.appendChild(tabScreenshots);
      }

      // Check if #timestamps exists inside #tab_screenshots
      var timestampsDiv = document.getElementById('timestamps');
      if (!timestampsDiv) {
        timestampsDiv = document.createElement('div');
        timestampsDiv.id = 'timestamps';
        tabScreenshots.appendChild(timestampsDiv);
      }

      // Create buttons with timestamps
      var timestamps = [firstTimestamp].concat(calculatedPercentages); // Include the first timestamp
      timestamps.forEach(function(timestamp) {
        var formattedTimestamp = formatTimeFromSeconds(timestamp);
        var button = document.createElement('button');
        button.textContent = formattedTimestamp;
        button.addEventListener('click', function() {
          flowplayer().seek(timestamp);
        });
        timestampsDiv.appendChild(button);
      });

    } else if (attempts < maxAttempts) {
      attempts++;
      setTimeout(checkDuration, intervalMs);
    } else {
      console.warn("Timeout: Unable to retrieve video duration.");
    }
  }

  checkDuration();
}

// Helper function to format time from seconds to mm:ss
function formatTimeFromSeconds(seconds) {
  var date = new Date(null);
  date.setSeconds(seconds);
  return date.toISOString().substr(14, 5);
}

// Example usage: Wait up to 10 attempts with 500ms interval
waitForVideoDuration(10, 500);








}




if (window.location.href.startsWith("https://www.camwhores.tv/playlists/") && window.location.href !== "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;
        }
    });

}

if(window.location.href.startsWith("https://www.camwhores.tv/edit-video/")){
  document.querySelector('.section-title.expand[data-expand-id="tab_screenshots"]').click();

  const elements = document.querySelectorAll("#tab_screenshots > div > div:nth-child(-n+5) > div.item-control > div.item-control-holder");
  elements.forEach(element => {
      element.addEventListener('click', () => {
          document.querySelector('input.submit[value="Save"]').click();
          if (history.length === 1) {
              window.close();
          }
      });
  });


    // console.log("history.length:",history.length)
}



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

if (window.location.href == "https://www.camwhores.tv/" || window.location.href == "https://www.camwhores.tv") {
    // HOME PAGE homepage
    let listVideos = document.querySelector("body > div.container > div.list_videos > div");
    let headline = document.querySelector("body > div.container > div.content > div.main-content > div.headline");
    let featuredVideosDates = document.querySelectorAll("#list_videos_featured_videos_items div.added");
    let latestVideoUpSeconds = convertToSeconds(featuredVideosDates[0].innerText);
    let latestStoredUpSeconds = parseInt(localStorage.getItem("cum_last_featuredVideoUpDate"));
  // console.log(latestStoredUpSeconds)
    let thereIsANewerVideo = latestVideoUpSeconds < latestStoredUpSeconds; // latest is less seconds old than the last stored

    function hideFtVideos(show){

      if (show) {
        listVideos.style.display = 'block';
        headline.style.paddingTop = '20px';
        document.querySelector("#🆕")?.style?.setProperty("display", "none");
      } else {
        listVideos.style.display = 'none';
        headline.style.paddingTop = '10px';

        localStorage.setItem("cum_last_featuredVideoUpDate", latestVideoUpSeconds)

      }
    }

    let showFeaturedVids = retrieveValueFromStorage("options")["cum_show_top"];
  console.log(showFeaturedVids)
    // if(showFeaturedVids === undefined) saveOption("cum_show_top", false)
    hideFtVideos(showFeaturedVids);


    let isChecked = showFeaturedVids ? 'checked' : '';
    document.querySelector("body > div.container > div.list_videos").insertAdjacentHTML('afterbegin', `
      <label class="switch" title="Top videos" id="cum_switch_top">
        <input type="checkbox" id="cum_show_top" ${isChecked}>
        <span class="slider round"></span>
      </label>
    `);
    let checkbox = document.querySelector('#cum_show_top');
    checkbox.addEventListener('change', function() {
      let checked = this.checked;
      hideFtVideos(checked)
      saveOption("cum_show_top", checked)
    });


    if(!showFeaturedVids && thereIsANewerVideo){
        let newEmoji = document.createElement('span');
        newEmoji.textContent = ' 🆕';
        newEmoji.id = '🆕';
        newEmoji.style = 'font-size:1.5rem;vertical-align:bottom;vertical-align:-webkit-baseline-middle'
        document.querySelector("body > div.container > div.list_videos").appendChild(newEmoji);
    }else{
        console.log("!showFeaturedVids:",!showFeaturedVids," && thereIsANewerVideo:",thereIsANewerVideo,"because:",latestVideoUpSeconds,">=",latestStoredUpSeconds)
    }


//     featuredVideosDates.forEach(div => {
//         let seconds = convertToSeconds(div.innerText);
//         console.log(div.innerText, seconds)
//     });

}







// 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 since updateLastVideoData,",(minutes - minutesOfAge), "to go");
        }
    }



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




// console.log(GM_info['script']['version']);


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","Holy See (Vatican City State)":"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"}}


// retrieveValueFromStorage
// saveValue


function updateAlert(){
        let lastCheck = retrieveValueFromStorage('lastVersionCheckDate');
        // console.log("lastCheck:",lastCheck)
        let lastVersionCheckDate;

        if (!lastCheck) {
            lastVersionCheckDate = currentDate;
        } else {
            lastVersionCheckDate = new Date(lastCheck);
        }

        let dateDifference = currentDate - lastVersionCheckDate;
        // console.log("dateDifference:",dateDifference)
        if(dateDifference > 3 * 24 * 60 * 60 * 1000){
            saveValue('lastVersionCheckDate', currentDate.toString());

            fetchAndParseHTML(metaPage, (htmlDoc) => {
                const metaContent = htmlDoc.body.textContent;
                const metaVersionMatch = metaContent.match(/@version\s+([^\s]+)/);
                if (metaVersionMatch) {
                    const latestVersion = metaVersionMatch[1];
                    console.log("Current version:",currentVersion,"Latest version:",latestVersion)


                    if (latestVersion !== currentVersion){
                        if (confirm('A new version of the CUM script is available.\nPlease allow automatic updates or update it manually.\nOpen in new tab?')){
                            GM_openInTab("https://sleazyfork.org/en/scripts/491272-camwhores-tv-utilities-mod");
                        }else{
                             toggleChange(updateRemindersOptionName, false);
                              console.log("Didn't confirm")
                        }
                    }
                }
            });
        }
}

if(updateReminders){
    updateAlert();
}









})();