Sleazy Fork is available in English.

Camwhores.tv Utilities Mod

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

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

(function() {
    'use strict';

    var _GM_registerMenuCommand, _GM_notification, options, optionName;
    const refreshVideosMinutes = 30;


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

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

    if (typeof GM_registerMenuCommand !== 'undefined') {
        _GM_registerMenuCommand = GM_registerMenuCommand;
    } else if (typeof GM !== 'undefined' && typeof GM.registerMenuCommand !== 'undefined') {
        _GM_registerMenuCommand = GM.registerMenuCommand;
    } else {
        // _GM_registerMenuCommand = (s, f) => { debug(s); debug(f); };
      console.log("Oh no");
    }



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

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

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

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

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


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

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

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

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

            textBox.value = delimitedString;

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

            document.body.appendChild(form);

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


    function optionsArrayEditor(array_name, optionsKeyLegible){

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

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

        });
    }

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

    });
}

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

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

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

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


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

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

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

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



    const style = document.createElement('style');
  // 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;
}

`;
    document.head.appendChild(style);



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

  function friendRequestSetup(video_title, video_url, userID){
    var vid_code = video_url.replace("https://www.camwhores.tv/videos/", "");
    var parts = vid_code.split("/");
    var videoId = parts[0];
    var code = parts[1];
    let cumData = {
        title: video_title,
        videoId: videoId,
        userId: userID
    };
    localStorage.setItem('last_cum_video_add', JSON.stringify(cumData));
  }

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


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


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

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

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

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

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

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



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

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

    let lastCheck = localStorage.getItem("UploadButtonTimestamp"); // EXAMPLE: "1717655623061"
    let minutesSinceLastCheck = secondsSinceTimestamp(lastCheck) / 60;
    let roundedMinutes = Math.floor(minutesSinceLastCheck);
    if(lastCheck && minutesSinceLastCheck > 30){
          getResponseStatus(uploadURL).then(status => {
              if (status === 200) {
                  alert("The upload button has been restored!")
                  localStorage.removeItem("UploadButtonTimestamp");
              } 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 ((window.location.href.endsWith("?action=reject_add_to_friends_done")) ||
        (window.location.href.endsWith("?action=confirm_add_to_friends_done"))) {

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


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







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

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






    function 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 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 if (currentPage === 1) {
      hasNewElements = true;
    }
  });

  if (currentPage === 1 && hasNewElements) {
    location.reload();
  }
}





// fixUnreadItem();



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

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

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

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

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

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

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


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

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




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

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

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


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




        setInterval(function() {
            processThumbnails()
            silentUidUpdater()
            checkAndFixMessages()
        }, 5000);


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

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




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

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

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

        // console.log(userID)


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

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



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

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

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

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


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

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

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

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





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

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

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

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







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

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



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

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

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

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

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

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


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

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






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

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

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

    }

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

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


              if(confirmClose){
                    let imgData = [];
                    for (let i = 1; i <= 5; i++) {
                        let xpath = `//*[@id="list_videos_uploaded_videos_items"]/div[${i}]/a/div[@class="img"]/img`;
                        let img = htmlDoc.evaluate(xpath, htmlDoc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
                        if (img) {
                            let parentAnchor = img.parentNode.parentNode;
                            imgData.push({ src: img.getAttribute('data-original'), alt: img.alt, url: parentAnchor.getAttribute('href') });
                        }
                    }
                        let vidPreviewsDiv = document.createElement("div");
                        vidPreviewsDiv.id = "vid_previews";
                        if (!isArrayEmpty(imgData)) {
                            imgData.forEach(data => {
                                let imgDiv = document.createElement("div");
                                imgDiv.classList.add("img-div");
                                let imgLink = document.createElement("a"); // New line
                                imgLink.href = data.url+"?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);
        // Check if the response status code indicates an error
        if (!response.ok) {
            console.error('Error loading video page:', response.status);
            return { byFriend: true, usernameID: null }; // Return true if there's an error loading the page
        }

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

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


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

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


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

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



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

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

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





        altThumbs && moveToSecondThumbnail();

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



        if (window.location.href.startsWith("https://www.camwhores.tv/members/")) {
            // USER PROFILE

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


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

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

              return newText;

          }





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

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

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



  function addSearchButton(){
          let sortElement = document.querySelector("#list_videos_uploaded_videos > div.headline > div.sort");
          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');

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

  form.appendChild(input);
  form.appendChild(submitButton);
  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);
  });
}

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;
    var timeoout = 75;
    if (approxTotalVideos > 500){
        timeoout = approxTotalVideos / 5;
    }
    if (totalVideoPages !== null) {
        let resultArray = [];
        let fetchPromises = []; // Array to store fetch promises

        for (let pageInt = 1; pageInt <= totalVideoPages; pageInt++) {
            let nextFivePages = userProfileAsyncURL(uid, pageInt);
            let fetchPromise = new Promise((resolve, reject) => {
                setTimeout(() => {
                    fetchAndParseHTML(nextFivePages, function(htmlDoc) {
                        let videos = htmlDoc.querySelectorAll('div#list_videos_uploaded_videos_items div.item');
                        videos.forEach(video => {
                            let title = video.querySelector('a').getAttribute('title');
                            let url = video.querySelector('a').getAttribute('href');
                            let imgSrc = video.querySelector('img').getAttribute('data-original');
                            let duration = video.querySelector('.duration').textContent.trim();
                            let isPrivate = video.classList.contains('private');
                             if (title.toLowerCase().includes(query.toLowerCase())) {
                                resultArray.push({
                                    title: title,
                                    private: isPrivate,
                                    url: url,
                                    imgSrc: imgSrc,
                                    duration: duration
                                });
                            }

                        });
                        resolve(); // Resolve the promise once fetchAndParseHTML is completed
                    });
                }, 75 * (pageInt - 1)); // Delay each fetch by 50ms
            });
            fetchPromises.push(fetchPromise);
        }

        // Wait for all fetch promises to resolve
        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";
          }
          userDescription.textContent = userDescription.textContent.replace(/^[\s\t]+/, '');






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







            updateVideoH2()
            addButtonEventListener()

      // console.log(friend_request_text)

      if (window.location.href.endsWith("#friends") && !window.location.href.includes("add_to_friends_done")) {
          let addButton = document.querySelector('a[href="#friends"][data-action="add_to_friends"]');
          let textarea = document.getElementById('add_to_friends_message');
          // let lastCumTitle = localStorage.getItem('last_cum_title');
          // let lastVidCode = localStorage.getItem('last_cum_vid_id');
          let lastAutoFriend = localStorage.getItem('last_auto_friend');
          let userId = window.location.href.split('/').slice(-2, -1)[0];
          // console.log(userId)

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


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

        if(!document.hasFocus()){
              window.close();
          }
        // 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(!document.hasFocus()){
                  window.close();
                }
      }

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

  } // END of member profile




        if(window.location.href.startsWith("https://www.camwhores.tv/videos/")){
            const element1 = document.querySelector('body > div.container > div.content > div.block-video > div.video-holder > div.player > div > div > span');
            const element2 = document.querySelector('body > div.container > div.content > div.block-album > div.album-holder > div.images > span.message');
            let username = document.querySelector('.username a').textContent.trim();
            let userId = document.querySelector('.username a').getAttribute('href').split('/').slice(-2, -1)[0];
                  // console.log(userId)
            if (element1 !== null || element2 !== null) {
                const href = document.querySelector('#tab_video_info > div > div.block-user > div > a').href;

                fetch(href)
                    .then(response => response.text())
                    .then(html => {
                    const htmlDoc = new DOMParser().parseFromString(html, 'text/html');
                    const infoMessage = htmlDoc.querySelector('.info-message');
                    if (infoMessage && infoMessage.textContent.includes("is in your friends list.")) {
                        const friends_string = "You're already friends! Reloading in 4 seconds";
                        (element1 || element2).textContent = friends_string;
                        setInterval(() => {
                            location.reload();
                        }, 4000);

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



        }




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

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

    h1Element.textContent = defaultTitle;

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

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

}



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

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

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





}







// ANY PAGE



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






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

        });*/




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

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

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

            callback(false);
        });
    }


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

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

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

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

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

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

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

        return elapsedTimeSeconds;
    }

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

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

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



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







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



})();