您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
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.7.4 // @description Info preview, removal of lock from friends' vidoes, restored upload button, and more. // @author vipprograms // @match https://www.camwhores.tv/* // @exclude *.camwhores.tv/*mode=async* // @grant GM_xmlhttpRequest // @grant GM.getValue // @grant GM_getValue // @grant GM.setValue // @grant GM_setValue // @grant GM_registerMenuCommand // @grant GM.registerMenuCommand // @grant GM_addStyle // @grant window.close // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAMUExURQAAAP8ANwwA/////7gbQJkAAAABdFJOUwBA5thmAAAAAWJLR0QDEQxM8gAAAAd0SU1FB+gDHhIuCjXV/h8AAAA4SURBVAjXY2ANDQ1gEA0NDWEIYWBgZAhgAAIUghEiC1YHBhpMDRpIhBbXghUMXKtWLWBgWqHVAACjlwz/pN0YPwAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyNC0wMy0zMFQxODo0NjowOSswMDowME+iXNIAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjQtMDMtMzBUMTg6NDY6MDkrMDA6MDA+/+RuAAAAKHRFWHRkYXRlOnRpbWVzdGFtcAAyMDI0LTAzLTMwVDE4OjQ2OjEwKzAwOjAwMNiA/AAAAABJRU5ErkJggg== // @require https://code.jquery.com/jquery-3.7.1.slim.min.js // ==/UserScript== (function() { 'use strict'; var _GM_registerMenuCommand, _GM_notification, options, optionName; const refreshVideosMinutes = 30; function isArrayEmpty(arr) { return arr.length === 0; } function retrieveValueFromStorage(key) { if (typeof GM_setValue === "function") { return GM_getValue(key, false); // Default value set to false for boolean } else if (typeof GM === "object" && typeof GM.getValue === "function" && typeof GM.setValue === "function") { return GM.getValue(key, false).then(function(value) { return value; }); } else { console.error("Unsupported userscript manager."); return undefined; } } function saveValue(key, array) { GM.setValue(key, array).then(function() { console.log("Array saved successfully."); }).catch(function(error) { console.error("Error saving array:", error); }); } if (typeof GM_registerMenuCommand !== 'undefined') { _GM_registerMenuCommand = GM_registerMenuCommand; } else if (typeof GM !== 'undefined' && typeof GM.registerMenuCommand !== 'undefined') { _GM_registerMenuCommand = GM.registerMenuCommand; } else { // _GM_registerMenuCommand = (s, f) => { debug(s); debug(f); }; console.log("Oh no"); } function toggleChange(options, optionName, defaultValue = false){ var updatedOptions; var currentState = options[optionName] !== undefined ? options[optionName] : defaultValue; _GM_registerMenuCommand((currentState ? "Disable " : "Enable ") + optionName, () => { currentState = !currentState; updatedOptions[optionName] = currentState; saveValue("options", updatedOptions); setTimeout(() => { location.reload(); }, 500); }); updatedOptions = retrieveValueFromStorage("options") || {}; // Ensure options exist if (updatedOptions[optionName] === undefined) { updatedOptions[optionName] = defaultValue; saveValue("options", updatedOptions); } } function createForm(array_name, delimitedString){ return new Promise((resolve, reject) => { var form = document.createElement('form'); form.classList.add('form-container'); var textBox = document.createElement('textarea'); textBox.classList.add('textarea-input'); textBox.setAttribute('autofocus', 'autofocus'); var buttonsLine = document.createElement('div'); buttonsLine.classList.add('buttons-line'); var submitButton = document.createElement('button'); submitButton.type = 'submit'; submitButton.textContent = 'Submit'; submitButton.classList.add('submit-button'); var cancelButton = document.createElement('button'); cancelButton.type = 'button'; cancelButton.textContent = 'Cancel'; cancelButton.classList.add('cancel-button'); cancelButton.addEventListener('click', function() { document.body.removeChild(form); reject('Form cancelled'); }); window.addEventListener('click', function(event) { if (document.body.contains(form) && !form.contains(event.target)) { document.body.removeChild(form); reject('Form cancelled'); } }); textBox.value = delimitedString; form.appendChild(textBox); form.appendChild(buttonsLine); buttonsLine.appendChild(cancelButton); buttonsLine.appendChild(submitButton); document.body.appendChild(form); form.addEventListener('submit', function(event){ event.preventDefault(); var inputValue = textBox.value.split('\n').map(line => line.trim()).filter(line => line !== ''); document.body.removeChild(form); resolve(inputValue); }); }); } function optionsArrayEditor(array_name, optionsKeyLegible){ _GM_registerMenuCommand("Change " + optionsKeyLegible[array_name], () => { var originalArray = retrieveValueFromStorage(array_name); var delimitedString = originalArray.join("\n"); createForm(array_name, delimitedString).then(lines => { saveValue(array_name, lines); }); }); } function optionsStringEditor(string_name, optionsKeyLegible) { _GM_registerMenuCommand("Change " + optionsKeyLegible[string_name], () => { var originalString = retrieveValueFromStorage(string_name); createForm(string_name, originalString).then(lines => { // Convert array 'lines' to a string by joining values with '\n' let stringifiedLines = lines.join('\n'); saveValue(string_name, stringifiedLines); }); }); } const auto_replies_default = ["Next time you send me a request with 0 videos, I'll block you", "Very nice videos", "Why? What's wrong?", "Sorry, I don't like your videos", "You don't have any videos"]; const highlight_keywords_default = ['joi', 'cei', 'fuck', "cumshot"]; const friend_request_text_default = "Hi! I'm interested in this video:"; var auto_replies = retrieveValueFromStorage("auto_replies"); var highlight_keywords = retrieveValueFromStorage("highlight_keywords"); var friend_request_text = retrieveValueFromStorage("friend_request_text"); if (!auto_replies) { auto_replies = auto_replies_default; saveValue("auto_replies", auto_replies_default); } if (!highlight_keywords) { highlight_keywords = highlight_keywords_default; saveValue("highlight_keywords", highlight_keywords_default); } if (!friend_request_text) { friend_request_text = friend_request_text_default; saveValue("friend_request_text", friend_request_text_default); } var optionsKeyLegible = { auto_replies: "template replies", highlight_keywords: "highlight keywords", friend_request_text: "friend requests text" } optionsArrayEditor("auto_replies", optionsKeyLegible) optionsArrayEditor("highlight_keywords", optionsKeyLegible) optionsStringEditor("friend_request_text", optionsKeyLegible) // BOOL OPTIONS options = retrieveValueFromStorage("options") optionName = "alternative thumbnails"; toggleChange(options, optionName, true) var altThumbs = retrieveValueFromStorage("options")[optionName]; optionName = "restore upload button"; toggleChange(options, optionName, true) var restoreUploadButton = retrieveValueFromStorage("options")[optionName]; optionName = "notify me of processed videos"; toggleChange(options, optionName, false) var notifyProcessedVideos = retrieveValueFromStorage("options")[optionName]; const style = document.createElement('style'); style.textContent = ` a.button{color:#4e4e4e !important;}ul > li.next, ul > li.prev {display: list-item !important;}.item:hover > a > div.img > .friends-tag, .item:hover > a > div.img > .videos-tag{background-color:#1a1a1a !important;}.button{color: rgb(183, 176, 167);text-align: center;border: 1px solid transparent;font-size: 14px;padding: 5px 10px;cursor: pointer;background: linear-gradient(to bottom, #ffffff 0%, #cccccc 100%);border-radius: 3px;display: inline-block;margin: 0 .3rem .3rem 0;color: dimgrey;}.button:hover{color: #f56c08 !important;border: 1px solid transparent;background: #1e1e1e;}div.img span.unread-notification{background: #c45606ab;backdrop-filter: blur(5px) brightness(1);top: 0px;left: 0px;border-bottom-left-radius: 3px;border-bottom-right-radius: 3px;outline: 3px solid #f56c08;animation: glow 5s infinite;}@keyframes glow {0% {outline-color: #f56c08d6;}50% {outline-color: transparent;}100% {outline-color: #f56c08d6;}}.form-container {box-sizing: border-box;position: fixed;top: 50%;left: 50%;transform: translate(-50%, -50%);max-width: 100vw;width: 800px;padding: 2.5rem;border-radius: .25rem;z-index:99999;background-color: transparent !important;backdrop-filter: blur(1rem) brightness(.8) contrast(1.2) }.form-container * {box-sizing: inherit;}.textarea-input {width: 100%;min-height: 10rem;padding: 1rem;border-radius: .25rem;color-scheme: dark !important;}.buttons-line {margin-top: .3rem;gap:.3rem;width: 100%;display: flex;}.submit-button:hover, .cancel-button:hover{filter: brightness(.8) contrast(1.2) }.submit-button, .cancel-button{transform: .3s;}.submit-button {height: 50px;flex-grow: 1;cursor: pointer;border-radius: .25rem;color-scheme: dark !important;font-weight:bold;border:0;}.cancel-button {width:min-content;height: 50px;cursor: pointer;border-radius: .25rem;color-scheme: dark !important;background-color: red;font-weight:bold;padding-inline:.5rem;border:0;}input.accept-button, span.accept-button {color: #fff;background-image: linear-gradient(rgb(0, 128, 0) 0%, rgb(0, 255, 0) 100%);}input.accept-button:hover, span.accept-button:hover {color: #fff !important;background-image: linear-gradient(rgb(34, 139, 34) 0%, rgb(50, 205, 50) 100%) !important;}input.reject-button, span.reject-button {color: #fff;background-image: linear-gradient(rgb(255, 0, 0) 0%, rgb(128, 0, 0) 100%);}input.reject-button:hover, span.reject-button:hover {color: #fff !important;background-image: linear-gradient(rgb(220, 20, 60) 0%, rgb(178, 34, 34) 100%) !important;}#vid_previews {display: flex;flex-wrap: nowrap;height: 135px;margin-block: .5rem;gap: 5px;box-sizing: border-box;}#vid_previews .img-div {width:185px;height:100%;position: relative;box-sizing: inherit;}.list-messages .added {position: absolute;right: 0;}.list-messages .item {margin-right: 0;}#vid_previews .img-div img{box-sizing: inherit;width: 100%;height:100%;}#vid_previews .img-div h2{position: absolute;bottom: 0;background-color: rgb(0 0 0 / 65%);font-size: 1rem;line-height: 1.2rem;backdrop-filter: blur(5px);color: rgb(196 196 196);width: 100%;word-wrap: break-word;box-sizing: inherit;text-align: center;}.bottom-element{margin-top: 1em;margin-bottom: 1em;}form .bottom{padding-top: .5rem;}form .bottom .submit{float: initial;height: auto;padding: .45rem .5rem;margin: 0;}.margin-fix .bottom{margin:0;}#gen_joined_text{margin: .5rem 0 .25rem 0;}a[href="http://flowplayer.org"], a[class="fp-brand"]{opacity: 0 !important;pointer-events: none !important;}div.block-profile > div > div > div.about-me > div > em{white-space:pre;} h1.online:after{ content: ''; height: .45rem; aspect-ratio: 1; display: inline-block; background-color: green; position: relative; left: .5rem; border-radius: 50%; bottom: .1rem; } `; document.head.appendChild(style); function makeValidUrlString(inputString) { var validString = inputString.replace(/[^\w\s\/-]/g, ''); // Remove special characters validString = validString.replace(/[-_]{2,}/g, '-'); // Turn consecutive underscores or hyphens into single hyphens validString = validString.replace(/\s+/g, '-'); // Turn spaces into hyphens validString = validString.replace(/\//g, '-'); // Turn slashes into hyphens return validString; } function friendRequestSetup(video_title, video_url, userID){ var vid_code = video_url.replace("https://www.camwhores.tv/videos/", ""); var parts = vid_code.split("/"); var videoId = parts[0]; var code = parts[1]; let cumData = { title: video_title, videoId: videoId, userId: userID }; localStorage.setItem('last_cum_video_add', JSON.stringify(cumData)); } function convertToSeconds(timeString) { let [_, value, unit] = timeString.match(/(\d+) (\w+)/); value = parseInt(value); switch (unit) { case 'second': case 'seconds': return value; case 'minute': case 'minutes': return value * 60; case 'hour': case 'hours': return value * 3600; case 'day': case 'days': return value * 86400; case 'week': case 'weeks': return value * 604800; case 'month': case 'months': return value * 2592000; // assuming 30 days per month case 'year': case 'years': return value * 31536000; // assuming 365 days per year default: return 0; } } function fetchAndParseHTML(url, callback) { GM_xmlhttpRequest({ method: "GET", url: url, onload: function(response) { var parser = new DOMParser(); var htmlDoc = parser.parseFromString(response.responseText, "text/html"); callback(htmlDoc); } }); } function fetchAndExtract(url, callback) { GM_xmlhttpRequest({ method: "GET", url: url, onload: function(response) { document.evaluate('//*[@id="list_messages_my_conversation_messages_items"]/div/div[3]/img', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue?.remove(); var parser = new DOMParser(); var htmlDoc = parser.parseFromString(response.responseText, "text/html"); callback(htmlDoc); } }); } /* usage: fetchAndExtract(messageUrl, function(htmlDoc) { }); */ function getAllSessionStorage() { var sessionStorageItems = {}; for (var i = 0; i < sessionStorage.length; i++) { var key = sessionStorage.key(i); var value = sessionStorage.getItem(key); sessionStorageItems[key] = value; } return sessionStorageItems; } function getCurrentPage(){ var allSessionStorage = getAllSessionStorage(); var paramsStorageKey = Object.keys(allSessionStorage).find(key => key.endsWith(":params")); if(!allSessionStorage || !paramsStorageKey){ return 1; } // console.log(allSessionStorage) // console.log("paramsStorageKey:",paramsStorageKey) var paramsValue = JSON.parse(allSessionStorage[paramsStorageKey]).from_my_conversations; // console.log("getCurrentPage:",getCurrentPage) return paramsValue; } function getCookie(name) { let cookieArr = document.cookie.split("; "); for(let cookie of cookieArr) { let [key, value] = cookie.split("="); if(key === name) return value; } return null; } function loadArrayLocalStorage(name='lastVideoData') { var jsonData = localStorage.getItem(name); if (!jsonData) { return []; } var data = JSON.parse(jsonData); return data; } function saveArrayLocalStorage(name='lastVideoData', data){ var timestamp = Date.now(); var jsonData = JSON.stringify(data); localStorage.setItem(name, jsonData); } function getNewUID() { let sessionStorageData = getAllSessionStorage(); if(!sessionStorageData){ return null; } for (let key in sessionStorageData) { let matches = key.match(/^(\d+):https:\/\/www\.camwhores\.tv/); if (matches) { return matches[1]; } } return null; } function saveUID(){ let uid = getNewUID(); if(uid){ let current_kt = getCookie("kt_member"); let data = {uid: uid, kt: current_kt}; saveArrayLocalStorage("cum_user_id", data); return uid; } return } function silentUidUpdater(){ let uidArray = loadArrayLocalStorage("cum_user_id"); if(!uidArray || getCookie("kt_member") !== uidArray.kt){ saveUID(); } } function currentUserID(){ let current_kt = getCookie("kt_member"); let uidArray = loadArrayLocalStorage("cum_user_id"); if(uidArray && uidArray.kt === current_kt){ return uidArray.uid; }else{ return saveUID() } return } async function getResponseStatus(url) { try { let response = await fetch(url, { method: 'HEAD' }); return response.status; } catch (error) { return null; } } let currentUID = currentUserID(); // console.log("User ID:", currentUID, "(https://www.camwhores.tv/members/" + currentUID + "/)") silentUidUpdater() // UPLOAD button const nav = document.querySelector('.navigation .primary'); if (nav && restoreUploadButton && ![...nav.querySelectorAll('a')].some(link => link.textContent.trim().includes('Upload'))) { const uploadLink = document.createElement('div'); uploadLink.style.backgroundColor = '#215521'; uploadLink.style.display = 'block'; uploadLink.style.padding = '11px 0'; uploadLink.style.cursor = 'pointer'; uploadLink.textContent = 'UPLOAD'; nav.appendChild(uploadLink); let uploadURL = '/upload-video/'; //'https://www.camwhores.tv/upload-video/' uploadLink.addEventListener('click', function() { getResponseStatus(uploadURL).then(status => { if (status === 200) { window.location.href = url; } else { alert("Upload functionality is currently fully disabled\n(" + status.toString() + ")"); // console.log(status) } }); }); }else{ console.log("Couldn't restoreUploadButton", restoreUploadButton) } if ((window.location.href.endsWith("?action=reject_add_to_friends_done")) || (window.location.href.endsWith("?action=confirm_add_to_friends_done"))) { let urlOfUser = document.querySelector('#list_messages_my_conversation_messages > div.headline > h2 > a:nth-child(2)') let username = urlOfUser.innerHTML.trim(); let userID = urlOfUser.getAttribute('href').match(/\/(\d+)\//)[1]; const storedData = JSON.parse(localStorage.getItem('closedWindow')); if (storedData) { let { uid, timestamp } = storedData; let currentTime = Date.now(); let timeDifference = (currentTime - timestamp) / 1000; // in seconds console.log(timeDifference + " seconds, uid: "+userID+" vs "+uid) if (timeDifference < 30 && userID == uid) { console.log(`Less than 30 seconds have passed since window closed. User ID: ${uid}`); window.close(); }else{ } } }else if (window.location.href == "https://www.camwhores.tv/my/messages/") { function myMessagesAsyncURL(pageInt=1){ const utcTimestamp = new Date().getTime(); const pageID = pageInt.toString(); return "https://www.camwhores.tv/my/messages/?mode=async&function=get_block&block_id=list_members_my_conversations&sort_by=added_date&from_my_conversations="+pageID+"&_="+utcTimestamp; } // console.log(myMessagesAsyncURL()) function currentPageInfo() { let urlToPage = myMessagesAsyncURL(getCurrentPage()); // console.log(urlToPage) return new Promise((resolve, reject) => { fetchAndExtract(urlToPage, function(htmlDoc) { const conversations = []; const items = htmlDoc.querySelectorAll("#list_members_my_conversations_items .item"); // console.log("htmlDoc:",htmlDoc) items.forEach(item => { const name = item.querySelector('a').getAttribute('title'); const unread = item.classList.contains('unread'); conversations.push({ name, unread }); }); resolve(conversations); }); }); } async function fixUnreadItem() { const infoArray = await currentPageInfo(); infoArray.forEach(item => { const conversationLink = document.querySelector(`#list_members_my_conversations_items > div.item > a[title="${item.name}"]`); if (conversationLink) { const unreadNotification = conversationLink.querySelector('div.img .unread-notification'); if (unreadNotification && !item.unread) { unreadNotification.remove(); console.log("Message with",item.name,"was read") } } }); } // fixUnreadItem(); function processThumbnails() { // console.log("Processing thumbnails"); var thumbnails = document.querySelectorAll('strong.title'); if (thumbnails.length === 0) { console.log("Thumbnails not found. Retrying in 1000 milliseconds."); setTimeout(function() { processThumbnails(); // Retry processing thumbnails }, 1000); return false; // Return false if thumbnails not found } thumbnails.forEach(function(thumbnail) { var usernameText = thumbnail.textContent.trim(); if (usernameText) { var usernameLink = document.querySelector('a[title="' + usernameText + '"]'); if (usernameLink) { var href = usernameLink.getAttribute('href'); var userIdMatch = href.match(/\/(\d+)\/$/); if (userIdMatch && userIdMatch.length > 1) { var userId = userIdMatch[1]; var usernameUrl = "https://www.camwhores.tv/members/" + userId + "/"; GM_xmlhttpRequest({ method: "GET", url: usernameUrl, onload: function(response) { var parser = new DOMParser(); var htmlDoc = parser.parseFromString(response.responseText, "text/html"); var infoMessage = htmlDoc.querySelector('.info-message'); var usernameLink = document.querySelector('a[title="' + usernameText + '"]'); // console.log(usernameText + ": " + usernameUrl) // console.log(usernameLink) if (infoMessage && infoMessage.textContent.includes("is in your friends list.")) { if (usernameLink) { var divElement = document.createElement('div'); divElement.classList.add("friends-tag"); divElement.textContent = "Friends ✅"; divElement.style.position = "absolute"; divElement.style.top = "0"; divElement.style.right = "0"; divElement.style.backgroundColor = "#414141"; //#1a1a1a divElement.style.borderBottomLeftRadius = "3px"; divElement.style.color = "white"; divElement.style.padding = "3px 5px"; if (usernameLink) { var firstDivElement = usernameLink.querySelector('div.img'); if (firstDivElement) { firstDivElement.appendChild(divElement); } } } } if(infoMessage && infoMessage.textContent.includes("wants to be your friend.")){ divElement = document.createElement('div'); divElement.textContent = "👀"; divElement.title = "Wants to be your friend!"; divElement.style.position = "absolute"; divElement.style.bottom = "0"; divElement.style.left = "0"; // divElement.style.backgroundColor = "aquamarine"; divElement.style.color = "white"; divElement.style.fontSize = "1rem"; divElement.style.padding = ".5rem .25rem"; if (usernameLink) { firstDivElement = usernameLink.querySelector('div.img'); if (firstDivElement) { firstDivElement.appendChild(divElement); } } } var titleVideosElement = htmlDoc.evaluate('//*[@id="list_videos_uploaded_videos"]/div[1]/h2', htmlDoc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null); var videoNumber = 0; if (titleVideosElement && titleVideosElement.singleNodeValue) { var titleVideosText = titleVideosElement.singleNodeValue.textContent; if (titleVideosText) { var matches = titleVideosText.match(/\(([^)]+)\)/); videoNumber = matches ? matches[1] : 0; } } if(videoNumber || videoNumber === 0){ divElement = document.createElement('div'); divElement.classList.add("videos-tag"); divElement.textContent = videoNumber; divElement.style.position = "absolute"; divElement.style.bottom = "0"; divElement.style.right = "0"; divElement.style.backgroundColor = "CadetBlue"; divElement.style.color = "white"; divElement.style.padding = "3px 5px"; divElement.style.borderTopLeftRadius = "3px"; } if (usernameLink) { firstDivElement = usernameLink.querySelector('div.img'); if (firstDivElement) { firstDivElement.appendChild(divElement); } } } // end httpGET reponse }); } else { console.log("User ID not found in href for:", usernameText); } } else { console.log("Username link not found for:", usernameText); } } }); return true; // Return true if thumbnails processed successfully } function addButtonEventListener() { // console.log("Adding event listener to buttons"); document.addEventListener('click', function(event) { var target = event.target; if (target && target.matches('a[data-action="ajax"]')) { // console.log("Button clicked"); var h2Element = document.querySelector('#list_members_my_conversations div.headline h2'); const initialText = h2Element.textContent.trim(); // console.log("Initial text: " + initialText); const checkChangeInterval = setInterval(function() { h2Element = document.querySelector('#list_members_my_conversations div.headline h2'); const currentText = h2Element.textContent.trim(); // console.log("Current text: " + currentText); if (currentText !== initialText) { clearInterval(checkChangeInterval); processThumbnails(); } }, 100); } }); } setTimeout(function() { processThumbnails(); var thumbnailsProcessed = processThumbnails(); if (!thumbnailsProcessed) { console.log("Processing thumbnails failed. Retrying in 1000 milliseconds."); setTimeout(function() { processThumbnails(); // Retry processing thumbnails }, 1000); } addButtonEventListener(); }, 1000); setInterval(function() { processThumbnails() fixUnreadItem() silentUidUpdater() }, 5000); const refreshIcon = document.createElement('span'); refreshIcon.innerHTML = '↻'; // Unicode for refresh icon refreshIcon.title = 'Refresh Utilities Mod'; refreshIcon.style.cursor = 'pointer'; refreshIcon.style.marginLeft = '10px'; // Adjust margin as needed refreshIcon.addEventListener('click', function() { processThumbnails() console.log('Refreshing...'); }); const h2Element = document.querySelector('#list_members_my_conversations .headline h2'); // console.log("adding..?") h2Element.appendChild(refreshIcon); }else if(window.location.href.startsWith("https://www.camwhores.tv/my/messages/")) { function updateButtonStyle(button, state) { if (state && button) { button.classList.add("accept-button"); } else if(button) { button.classList.add("reject-button"); // console.log(button) }else{ // console.log(button + " button absent") } } let textarea = document.querySelector("#send_message_message"); let divTextarea = document.createElement('div'); let urlOfUser = document.querySelector('#list_messages_my_conversation_messages > div.headline > h2 > a:nth-child(2)') let username = urlOfUser.innerHTML.trim(); let userID = urlOfUser.getAttribute('href').match(/\/(\d+)\//)[1]; let confirmButton = document.querySelector('input[name="confirm"]'); let rejectButton = document.querySelector('input[name="reject"]'); let buttonsParent = confirmButton ? confirmButton.parentElement : null; let confirmClose = null let denyClose = null // console.log(userID) document.querySelector('input.submit').addEventListener('click', function() { divTextarea.innerHTML = ''; }); $(document).ready(function() { $(document).keyup(function(event) { if (event.ctrlKey && event.key === 'Enter') { event.preventDefault(); alert("Submitting"); $("#send_message_form").submit(); } }); }); function copyContentToTextarea() { const tempDiv = document.createElement('div'); tempDiv.innerHTML = divTextarea.innerHTML; const content = []; tempDiv.childNodes.forEach(node => { if (node.nodeType === 3) { // Text node content.push(node.textContent); } else if (node.nodeType === 1 && node.tagName === 'IMG') { // Image node content.push(node.alt); } }); const finalText = content.join('').trim(); // Join text content and alt attributes with space textarea.value = finalText; // Set the final text to the textarea } textarea.style.display = "none"; divTextarea.innerHTML = textarea.value; divTextarea.contentEditable = true; divTextarea.style.minHeight = "5rem"; divTextarea.style.resize = "vertical"; divTextarea.style.overflow = "auto"; divTextarea.style.fontSize = "14px"; divTextarea.classList.add("textarea"); textarea.parentNode.insertBefore(divTextarea, textarea.nextSibling); document.querySelectorAll('.smileys-bar img').forEach(function(img) { img.addEventListener('click', function(event) { event.preventDefault(); event.stopPropagation(); var imgClone = img.cloneNode(true); imgClone.style.cursor = "auto"; // Add cursor style divTextarea.appendChild(imgClone); copyContentToTextarea() return false; }); }); divTextarea.addEventListener('input', copyContentToTextarea); var inlineTexts = document.querySelectorAll('span.inline-text, span.original-text'); inlineTexts.forEach(function(span) { var lineText = span.textContent.trim(); if (lineText.includes('##')) { var index = lineText.indexOf(':'); var videoText = lineText.substring(0, index).trim(); var videoInfo = lineText.substring(index + 1).trim().replace('##', ''); let parts = videoInfo.split("\n"); let videoCode = parts[0]; let videoID = parts[1]; let url = 'https://www.camwhores.tv/videos/' + videoID + "/" + makeValidUrlString(videoCode) + '/'; // console.log(url) fetch(url) .then(response => { if (response.ok) { span.innerHTML = videoText + ': <a href="' + url + '" class="toggle-button" style="display:inline-block">'+videoCode+'</a>'; } else if (response.status === 404) { console.log("URL is 404"); } else { console.error("Error:", response.status); } }) .catch(error => console.error("Error:", error)); // span.innerHTML = videoText + ': <a href="' + url + '" class="toggle-button" style="display:inline-block">Open video</a>'; } }); function andClosePage(){ const closedWindow = { uid: userID, timestamp: Date.now() }; localStorage.setItem('closedWindow', JSON.stringify(closedWindow)); console.log("Window should close now") window.close(); } function addCloseButtonsListeners(confirmButton, rejectButton) { var confirmClose, denyClose; if (confirmButton) { var buttonsParent = confirmButton.parentElement; confirmClose = document.createElement('span'); confirmClose.className = 'submit button'; confirmClose.innerHTML = 'Confirm & Close'; denyClose = document.createElement('span'); denyClose.className = 'submit button'; denyClose.innerHTML = 'Deny & Close'; confirmClose.addEventListener('click', function(event) { event.preventDefault(); // alert("Clicked! (when done debugging, REMOVE and CLOSE)") confirmButton.click(); andClosePage() }); denyClose.addEventListener('click', function(event) { event.preventDefault(); // alert("Clicked! (when done debugging, REMOVE and CLOSE)") rejectButton.click(); andClosePage() }); var closeButtonsContainer = document.createElement('div'); closeButtonsContainer.classList.add('closeInputs'); buttonsParent.appendChild(confirmClose); buttonsParent.appendChild(document.createTextNode(' ')); buttonsParent.appendChild(denyClose); buttonsParent.appendChild(closeButtonsContainer); confirmButton.style.width = confirmClose.offsetWidth + 'px'; rejectButton.style.width = denyClose.offsetWidth + 'px'; } return { confirmClose: confirmClose, denyClose: denyClose }; } function updateMessageDOM(htmlDoc, confirmClose, denyClose) { var titleText = htmlDoc.querySelector('#list_videos_uploaded_videos > div:nth-child(1) > h2')?.textContent.trim(); var lastUploadTime = htmlDoc.querySelector('#list_videos_uploaded_videos_items > div.item > a > div.wrap > div.added > em')?.textContent.trim(); var joinedDateText = htmlDoc.querySelector('div.block-profile > div.profile-list > div.margin-fix > div.column > div:nth-child(3) > em')?.textContent.trim(); var lastLogin = htmlDoc.querySelector('div.block-profile > div.profile-list > div.margin-fix > div.last-login > div.item')?.textContent.trim(); let seconds = convertToSeconds(lastLogin); let recentlyOnline = seconds <= 300; // let recentlyOnline = true; const headlineH2 = document.querySelector('#list_messages_my_conversation_messages .headline h2'); console.log("recentlyOnline:", recentlyOnline); if(recentlyOnline){ GM_addStyle(`.list-messages .item.new .added:after { background-color: green; }`); document.querySelector("#list_messages_my_conversation_messages_items > div.item.new > div.added").textContent += " (online)"; headlineH2.innerHTML += " (online)" } if (titleText) { // THERE ARE VIDEOS var extractedTitle = titleText.match(/\(([^)]+)\)/); if (extractedTitle && extractedTitle.length > 1) { // THERE ARE VIDEOS updateButtonStyle(confirmButton, true); updateButtonStyle(confirmClose, true); var generatedTextDiv = document.createElement('div'); generatedTextDiv.id = 'gen_joined_text'; generatedTextDiv.innerHTML = `Joined ${joinedDateText}<br>${extractedTitle[1]} videos, last ${lastUploadTime}`; var messageDiv = document.querySelector('#list_messages_my_conversation_messages_items > div > div:nth-child(3)'); if (messageDiv) { messageDiv.appendChild(generatedTextDiv); } } if(confirmClose){ let imgData = []; for (let i = 1; i <= 5; i++) { let xpath = `//*[@id="list_videos_uploaded_videos_items"]/div[${i}]/a/div[@class="img"]/img`; let img = htmlDoc.evaluate(xpath, htmlDoc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; if (img) { let parentAnchor = img.parentNode.parentNode; imgData.push({ src: img.getAttribute('data-original'), alt: img.alt, url: parentAnchor.getAttribute('href') }); } } let vidPreviewsDiv = document.createElement("div"); vidPreviewsDiv.id = "vid_previews"; if (!isArrayEmpty(imgData)) { imgData.forEach(data => { let imgDiv = document.createElement("div"); imgDiv.classList.add("img-div"); let imgLink = document.createElement("a"); // New line imgLink.href = data.url; // New line let img = document.createElement("img"); img.src = data.src; img.alt = data.alt; img.title = data.alt; let title = document.createElement("h2"); title.textContent = data.alt; imgLink.appendChild(img); // Updated line imgDiv.appendChild(imgLink); // Updated line imgDiv.appendChild(title); vidPreviewsDiv.appendChild(imgDiv); }); buttonsParent.appendChild(vidPreviewsDiv); } } } else { // THERE ARE NO VIDEOS console.log('No videos? Title: '+titleText+", content: "+lastUploadTime); updateButtonStyle(rejectButton, false); updateButtonStyle(denyClose, false); var messageDiv = document.querySelector('#list_messages_my_conversation_messages_items > div > div:nth-child(3)'); if (messageDiv) { var generatedTextDiv = document.createElement('div'); generatedTextDiv.id = 'gen_joined_text'; generatedTextDiv.innerHTML = `Joined ${joinedDateText}<br><b>No videos</b>`; messageDiv.appendChild(generatedTextDiv); } } } // return var bottomDiv = document.querySelector("#send_message_form > div > div.bottom"); var responsesDiv = document.createElement("div"); responsesDiv.id = "responses"; responsesDiv.style.marginTop = "1rem"; bottomDiv.insertAdjacentElement('afterend', responsesDiv); auto_replies.forEach(function(string) { var button = document.createElement("button"); button.textContent = string; button.classList.add("button"); button.addEventListener("click", function(event) { event.preventDefault(); if (textarea.value.trim() !== '') { textarea.value += "\n"; } textarea.value += string; document.querySelector('#send_message_form').submit(); }); button.style.padding = ".25rem .5rem" responsesDiv.appendChild(button); }); // return // var messageLink = document.evaluate('//*[@id="list_messages_my_conversation_messages"]/div[1]/h2/a[2]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null); var messageLink = document.evaluate('//*[@id="list_messages_my_conversation_messages_items"]/div/div[1]/a', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null); if (messageLink && messageLink.singleNodeValue) { var messageUrl = messageLink.singleNodeValue.href; const parentElement = document.evaluate('//*[@id="list_messages_my_conversation_messages_items"]/div/div[3]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; const img = document.createElement('img'); img.src = 'https://samherbert.net/svg-loaders/svg-loaders/three-dots.svg'; // loading spinner img.style.height = "32px"; img.style.width = "32px"; parentElement.appendChild(img); fetchAndExtract(messageUrl, function(htmlDoc) { var closeButtons = addCloseButtonsListeners(confirmButton, rejectButton); var confirmClose = closeButtons.confirmClose; var denyClose = closeButtons.denyClose; updateMessageDOM(htmlDoc, confirmClose, denyClose); }); } else { console.log('Message link not found.'); } // AESTHETIC CHANGE var bottomElement = document.evaluate('//*[@id="list_messages_my_conversation_messages_items"]/div/div[3]/form/div', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; if (bottomElement && bottomElement.singleNodeValue) { bottomElement.classList.add('bottom-element'); bottomElement.singleNodeValue.style.marginTop = "1em"; bottomElement.singleNodeValue.style.marginBottom = "1em"; bottomElement.singleNodeValue.style.outline = "2px solid red"; bottomElement.singleNodeValue.classList.remove("bottom"); } }else if(window.location.href !== "https://www.camwhores.tv/my/videos/") { // Set to store unique video elements const processedVideos = new Set(); function addPrivateVideos() { const private_videos = []; const videoElements = document.querySelectorAll('.line-premium, .line-private'); videoElements.forEach(video => { const parentDiv = video.parentElement; if ( parentDiv.tagName === 'DIV' && parentDiv.parentElement.tagName === 'A' && !processedVideos.has(parentDiv.parentElement) ) { private_videos.push(parentDiv.parentElement); processedVideos.add(parentDiv.parentElement); } }); return private_videos; } async function checkVideoPage(url) { try { const response = await fetch(url); // Check if the response status code indicates an error if (!response.ok) { console.error('Error loading video page:', response.status); return { byFriend: true, usernameID: null }; // Return true if there's an error loading the page } const html = await response.text(); const parser = new DOMParser(); const doc = parser.parseFromString(html, 'text/html'); const hasElement1 = doc.querySelector('body > div.container > div.content > div.block-video > div.video-holder > div.player > div > div > span') !== null; const hasElement2 = doc.querySelector('body > div.container > div.content > div.block-album > div.album-holder > div.images > span.message') !== null; // basically the "This video is a private video uploaded by" message const userURL = doc.querySelector('.username a').href; var vid_code = userURL.replace("https://www.camwhores.tv/members/", ""); var usernameID = vid_code.split("/")[0]; return { byFriend: hasElement1 || hasElement2, usernameID: usernameID }; } catch (error) { console.error('Error checking video page:', error); return { byFriend: false, usernameID: null }; } } async function applyStyleToPrivateVideos() { const privateVideos = addPrivateVideos(); for (const video of privateVideos) { let videoLink = video.getAttribute('href'); let videoTitle = video.querySelector('strong.title').textContent.trim(); let { byFriend: hasElement, usernameID } = await checkVideoPage(videoLink); // console.log(videoLink + " " + hasElement); if (!hasElement) { video.style.outline = 'green solid 2px'; const linePrivate = video.querySelector('div > .line-private'); if (linePrivate) { linePrivate.style.display = 'none'; } let imgElement = video.querySelector('div > img'); if (imgElement) { imgElement.style.opacity = '1'; } }else{ // add ❌ const linePrivate = video.querySelector('div > .line-private > span'); if (linePrivate) { linePrivate.textContent += ' ❌'; const addFriend = document.createElement('a'); addFriend.textContent = '➕'; addFriend.title = 'Friend request'; addFriend.href = "https://www.camwhores.tv/members/" + usernameID + "/#friends"; addFriend.style.zIndex = '10'; addFriend.style.position = 'absolute'; addFriend.style.bottom = '20px'; addFriend.style.right = '0'; addFriend.style.fontSize = '1rem'; addFriend.style.padding = '5px 2.5px'; addFriend.style.backgroundColor = 'hsla(0, 0%, 0%, 0.7)'; addFriend.addEventListener('click', function(event) { // alert(videoTitle) event.stopImmediatePropagation(); friendRequestSetup(videoTitle, videoLink, usernameID) }); let thumbDiv = video.querySelector('.img') thumbDiv.appendChild(addFriend); // video.style.outline = "2px solid red" } } await new Promise(resolve => setTimeout(resolve, 25)); // avoid 503 } } applyStyleToPrivateVideos(); function findRelevantKeywords() { const titles = document.querySelectorAll('.title'); titles.forEach(title => { const originalText = title.innerHTML; highlight_keywords.forEach(keyword => { const regex = new RegExp(keyword, 'gi'); if (originalText.match(regex)) { const highlightedText = originalText.replace(regex, '<span style="color: green;">$&</span>'); title.innerHTML = highlightedText; } }); }); } findRelevantKeywords() // Define a global array to store blacklisted image sources const blacklist = []; function moveToSecondThumbnail() { $('.thumb.lazy-load').off('mouseover').off('mouseout'); document.querySelectorAll('.thumb.lazy-load').forEach(image => { const src = image.getAttribute('src'); if (blacklist.includes(src)) { return; } const newSrc = src.replace('1.jpg', '2.jpg'); // console.log("ye") if (src && src.endsWith('1.jpg')) { image.setAttribute('src', newSrc); } const images = ['3.jpg', '4.jpg', '5.jpg', '1.jpg', '2.jpg']; let currentIndex = 0; let intervalId; const loopImages = () => { if (src && src.endsWith('jpg')) { const newSrcName = images[currentIndex]; const newSrc = src.substring(0, src.length - 5) + newSrcName; // console.log(newSrc) image.setAttribute('src', newSrc); currentIndex = (currentIndex + 1) % images.length; } }; const mouseoverHandler = () => { clearInterval(intervalId); intervalId = setInterval(loopImages, 500); }; const mouseoutHandler = () => { if (src && src.endsWith('1.jpg') && !(blacklist.includes(src))) { image.setAttribute('src', newSrc); } clearInterval(intervalId); }; // Create a new image element to check if the original image was loaded successfully const testImage = new Image(); testImage.src = src; testImage.onload = function() { // Image loaded successfully // console.log('Image loaded successfully:', src); }; testImage.onerror = function() { // Image failed to load (404 error) // console.log('Image failed to load (404 error):', src); blacklist.push(src); image.setAttribute('src', src); // Remove previous mouseover and mouseout event listeners image.removeEventListener('mouseover', mouseoverHandler); image.removeEventListener('mouseout', mouseoutHandler); }; // Add mouseover and mouseout event listeners image.addEventListener('mouseover', mouseoverHandler); image.addEventListener('mouseout', mouseoutHandler); }); // console.log(blacklist); } altThumbs && moveToSecondThumbnail(); setInterval(() => { applyStyleToPrivateVideos(); findRelevantKeywords() altThumbs && moveToSecondThumbnail(); }, 750); // Interval in milliseconds (every second) if (window.location.href.startsWith("https://www.camwhores.tv/members/")) { // USER PROFILE function userProfileAsyncURL(uid,pageInt){ const utcTimestamp = new Date().getTime(); const pageID = pageInt.toString(); return "https://www.camwhores.tv/members/"+uid+"/?mode=async&function=get_block&block_id=list_videos_uploaded_videos&sort_by=&from_videos="+pageID+"&_="+utcTimestamp; } function numberBetweenParenthesis(text){ if(!text){ return } const matches = text.match(/\((\d+)\)/); if (matches && matches.length > 1) { return parseInt(matches[1]); } return null; } function getRoundedTotalPages(userVideosH2) { const text = userVideosH2?.textContent; let videos_total = numberBetweenParenthesis(text); return Math.ceil(videos_total / 5); } // console.log("getRoundedTotalPages():",getRoundedTotalPages(userVideosH2)); function updateVideoH2() { let userVideosH2 = document.querySelector('#list_videos_uploaded_videos .headline h2'); if(!userVideosH2){ return; } const rounded_videos_total = getRoundedTotalPages(userVideosH2); let newText = '/' + rounded_videos_total; // console.log(userVideosH2) if (rounded_videos_total !== null) { const innerHTML = userVideosH2.innerHTML.trim(); if (innerHTML.includes("Page")) { userVideosH2.innerHTML = innerHTML + newText; } }else{ console.log("rounded_videos_total is null inside updateVideoH2()") } return newText; } const userVideosH2 = document.querySelector('#list_videos_uploaded_videos .headline h2'); const rounded_videos_total = getRoundedTotalPages(userVideosH2); const userDescription = document.querySelector("div.block-profile > div.profile-list > div > div.about-me > div > em") const lastLogin = document.querySelector('div.block-profile > div.profile-list > div.margin-fix > div.last-login > div.item')?.textContent.trim(); const userId = window.location.href.split('/').slice(-2, -1)[0]; let seconds = convertToSeconds(lastLogin); let recentlyOnline = seconds <= 300; let h1 = document.querySelector("h1"); const country = document.querySelector('div.block-profile > div.profile-list > div.margin-fix > div.column > div:nth-child(1) > em'); const countryName = country.textContent.trim() let countryCode = contryCodesArray()[countryName] || []; const parent = document.querySelector('div.block-profile > div.profile-list > div.margin-fix > div.column > div:nth-child(1)'); function videoSearch(userVideosH2, uid, query) { let videosTotal = getRoundedTotalPages(userVideosH2); if (videosTotal !== null) { let resultArray = []; for (let pageInt = 1; pageInt <= videosTotal; pageInt++) { let nextFivePages = userProfileAsyncURL(uid, pageInt); // console.log(nextFivePages) fetchAndParseHTML(nextFivePages, function(htmlDoc) { let videos = htmlDoc.querySelectorAll('div#list_videos_uploaded_videos_items div.item'); videos.forEach(video => { let title = video.querySelector('a').getAttribute('title'); let url = video.querySelector('a').getAttribute('href'); let imgSrc = video.querySelector('img').getAttribute('data-original'); let duration = video.querySelector('.duration').textContent.trim(); let isPrivate = video.classList.contains('private'); if (title.includes(query)) { resultArray.push({ private: isPrivate, url: url, imgSrc: imgSrc, duration: duration }); } }); }); } return resultArray; } return null; } // let search = videoSearch(userVideosH2, userId, "Becky"); // console.log(search) function addButtonEventListener() { document.addEventListener('click', function(event) { var target = event.target; if (target && target.matches('a[data-action="ajax"]')) { const sessionStorageIndex = getCurrentUserVideoLocation(); if (sessionStorageIndex) { // console.log("Session storage index found:", sessionStorageIndex); waitForSessionStorageChange(); } else { console.log("Session storage index not found"); } } }); } function getCurrentUserVideoLocation() { let uid = currentUserID(); let userVideoLocation = uid + ":https://www.camwhores.tv/members/" + userId + "/#list_videos_uploaded_videos:params"; return sessionStorage.getItem(userVideoLocation); } function waitForSessionStorageChange() { // console.log("Waiting for session storage change"); const initialSessionStorageValue = getCurrentUserVideoLocation(); // console.log("Initial session storage value:", initialSessionStorageValue); const checkChangeInterval = setInterval(function() { const currentSessionStorageValue = getCurrentUserVideoLocation(); // console.log("Current session storage value:", currentSessionStorageValue); if (currentSessionStorageValue !== initialSessionStorageValue) { // console.log("Session storage value changed"); clearInterval(checkChangeInterval); updateVideoH2(); } }, 50); } if(recentlyOnline){ h1.textContent += " (online)"; h1.className = "online"; } userDescription.textContent = userDescription.textContent.replace(/^[\s\t]+/, ''); if (countryCode && countryName !== "no info") { country.remove(); const img = document.createElement('img'); img.src = `https://flagcdn.com/${countryCode}.svg`; img.width = 35; img.alt = countryName; img.title = countryName; img.style ="position:absolute;top: 50%;transform: translateY(-50%);left:4rem;" parent.appendChild(img); parent.style.position = "relative"; } updateVideoH2() addButtonEventListener() // console.log(friend_request_text) if (window.location.href.endsWith("#friends") && !window.location.href.includes("add_to_friends_done")) { let addButton = document.querySelector('a[href="#friends"][data-action="add_to_friends"]'); let textarea = document.getElementById('add_to_friends_message'); // let lastCumTitle = localStorage.getItem('last_cum_title'); // let lastVidCode = localStorage.getItem('last_cum_vid_id'); let lastAutoFriend = localStorage.getItem('last_auto_friend'); let userId = window.location.href.split('/').slice(-2, -1)[0]; // console.log(userId) let retrievedData = JSON.parse(localStorage.getItem('last_cum_video_add')); let lastCumTitle = retrievedData.title; let lastVidCode = retrievedData.videoId; let lastUserID = retrievedData.userId; let pageTitle = document.title; let username = pageTitle.replace("'s Page", ""); if (textarea !== null && !addButton.classList.contains('done') && username !== lastAutoFriend && lastCumTitle !== null && addButton !== null) { textarea.value = ""; if(userId === lastUserID){ textarea.value += friend_request_text + " " + lastCumTitle + "\n##" + lastVidCode; } document.querySelector('input[type="submit"].submit[value="Invite"]').click(); localStorage.setItem('last_auto_friend', username); addButton.click(); // final submit button if(!document.hasFocus()){ window.close(); } }else if(!document.hasFocus() && addButton.classList.contains('done')){ window.close(); } }else if(window.location.href.includes("add_to_friends_done")){ let addButton = document.querySelector('a[href="#friends"][data-action="add_to_friends"]'); if (addButton !== null && !addButton.classList.contains('done')) { addButton.classList.add('done'); } } // console.log("document.hasFocus():",document.hasFocus()) } // END of member profile if(window.location.href.startsWith("https://www.camwhores.tv/videos/")){ const element1 = document.querySelector('body > div.container > div.content > div.block-video > div.video-holder > div.player > div > div > span'); const element2 = document.querySelector('body > div.container > div.content > div.block-album > div.album-holder > div.images > span.message'); let username = document.querySelector('.username a').textContent.trim(); let userId = document.querySelector('.username a').getAttribute('href').split('/').slice(-2, -1)[0]; // console.log(userId) if (element1 !== null || element2 !== null) { const href = document.querySelector('#tab_video_info > div > div.block-user > div > a').href; fetch(href) .then(response => response.text()) .then(html => { const htmlDoc = new DOMParser().parseFromString(html, 'text/html'); const infoMessage = htmlDoc.querySelector('.info-message'); if (infoMessage && infoMessage.textContent.includes("is in your friends list.")) { const friends_string = "You're already friends! Reloading in 4 seconds"; (element1 || element2).textContent = friends_string; setInterval(() => { location.reload(); }, 4000); } else { console.log("Not friends!"); var infoElement = null; if(element1 !== null){ infoElement = element1 }else{ infoElement = element2 } let headline = document.querySelector('body > div.container > div.content > div.headline > h1'); if (headline !== null) { let title = headline.textContent.trim(); var currentUrl = window.location.href; friendRequestSetup(title, currentUrl, userId); const userProfileUrl = infoElement.querySelector('a').getAttribute('href') + "#friends"; // console.log(userProfileUrl) const toggleButton = document.createElement('a'); toggleButton.classList.add("button"); toggleButton.textContent = "Send request"; toggleButton.href = userProfileUrl toggleButton.style.display= "inline-block"; toggleButton.style.display= "#4e4e4e"; infoElement.appendChild(document.createElement('br')); infoElement.appendChild(toggleButton); } else { console.log("Element not found"); } // Screenshots document.querySelectorAll('.block-screenshots .item.private').forEach(function(el) { let newEl = document.createElement('a'); newEl.innerHTML = el.innerHTML; el.parentNode.replaceChild(newEl, el); let img = newEl.querySelector('img'); if(!img) { return; } img.src = img.getAttribute('data-original'); let srcThumb = img.getAttribute('data-original'); let srcBig = srcThumb.replace('/videos_screenshots/', '/videos_sources/').replace('/180x135/', '/screenshots/'); newEl.href = srcBig; newEl.classList.add('item'); newEl.setAttribute('rel', 'screenshots'); newEl.setAttribute('data-fancybox-type', 'image'); }); } // END not friends }) .catch(error => console.error('Error fetching:', error)); } } if (window.location.href.startsWith("https://www.camwhores.tv/playlists/")) { console.log("Playlist!"); let h1Element = document.querySelector('h1'); let playlistItem = document.querySelector('#playlist_view_playlist_view_items a'); let defaultTitle = playlistItem.querySelector('.title').textContent.trim(); let defaultHref = playlistItem.href; h1Element.textContent = defaultTitle; let openVidButton = document.createElement('a'); openVidButton.classList.add("button"); openVidButton.textContent = "Open video"; openVidButton.href = defaultHref; openVidButton.style.padding = "5px 5px 0 5px"; h1Element.parentElement.appendChild(openVidButton); document.addEventListener('click', function(e) { let playlistItem = e.target.closest('#playlist_view_playlist_view_items a'); if (playlistItem) { let videoTitle = playlistItem.querySelector('.title').textContent.trim(); let videoHref = playlistItem.href; console.log("Clicked", videoTitle); h1Element.textContent = videoTitle; openVidButton.href = videoHref; } }); } } // end of (NOT "/my/videos/") if (window.location.href === "https://www.camwhores.tv/my/") { // console.log("HELLO PROFILE") let profileCSS = document.createElement('style'); profileCSS.className = "profile-css"; profileCSS.textContent = ` #edit_profile_about_me{ height:225px; } strong.popup-title, span.selection [role="combobox"]{ display:none; } body > div.fancybox-overlay.fancybox-overlay-fixed > div{ top:0 !important; height: 100svh !important; } body > div.fancybox-overlay.fancybox-overlay-fixed, body > div.fancybox-overlay.fancybox-overlay-fixed > *{ box-sizing: border-box; } div.fancybox-inner{ height:100% !important; width: max-content !important; } .fancybox-close{ top:9px !important; } `; document.head.appendChild(profileCSS); } // ANY PAGE function myVideosAsyncURL(pageInt){ const utcTimestamp = new Date().getTime(); const pageID = pageInt.toString(); return "https://www.camwhores.tv/my/videos/?mode=async&function=get_block&block_id=list_videos_my_uploaded_videos&sort_by=&from_my_videos="+pageID+"&_="+utcTimestamp; } /* fetchAndParseHTML("https://www.camwhores.tv/my/", function(htmlDoc) { console.log(htmlDoc) });*/ function pagesLastProcessedVideo(page, callback) { fetchAndParseHTML(myVideosAsyncURL(page), function(htmlDoc) { const videoItems = htmlDoc.querySelectorAll("#list_videos_my_uploaded_videos_items > form > div.item.private"); let lastProcessingIndex = -1; for (let i = videoItems.length - 1; i >= 0; i--) { if (videoItems[i].classList.contains('processing')) { lastProcessingIndex = i; break; } } if (lastProcessingIndex !== -1 && lastProcessingIndex < videoItems.length - 1) { const precedingItem = videoItems[lastProcessingIndex + 1]; const checkbox = precedingItem.querySelector(".item-control-holder .toggle-button input[type='checkbox']"); if (checkbox) { callback(checkbox.value); return; } } callback(false); }); } function lastProcessedVideoID(callback) { var found = false; var completedIterations = 0; let maxPages = 3; for (var pageN = 1; pageN <= maxPages; pageN++) { (function(page) { pagesLastProcessedVideo(page, function(checkboxValue) { completedIterations++; // Increment the counter for each completed iteration if (checkboxValue && !found) { found = true; callback(checkboxValue); } else if (completedIterations === maxPages && !found) { // Check if all iterations have completed and no checkbox value is found callback(false); } }); })(pageN); } } function loadLastVideoData() { var jsonData = localStorage.getItem('lastVideoData'); if (!jsonData) { return [null, null]; // No stored data, return null values } var data = JSON.parse(jsonData); return data; } function lastVideoDataAge(refreshMinutes=30) { var data = loadLastVideoData(); if (!data[1]) { // Timestamp console.log("Force recheck") var bigTime = (refreshMinutes * 60) + 1; // bigTime = 0; return bigTime; // No stored timestamp, assume age is 0 seconds } var timestamp = data[1]; var currentTime = Date.now(); var elapsedTimeSeconds = (currentTime - timestamp) / 1000; return elapsedTimeSeconds; } function saveLastVideoID(callback) { const lastID = loadLastVideoData()[0]; lastProcessedVideoID(function(currentID) { var timestamp = Date.now(); var data = [currentID, timestamp]; // Include lastID and currentID in the data array var jsonData = JSON.stringify(data); localStorage.setItem('lastVideoData', jsonData); callback(lastID, currentID); // Invoke the callback with both lastID and currentID console.log("Last ID:", lastID, "\nCurrent ID:", currentID, "(https://www.camwhores.tv/edit-video/"+currentID+"/)"); }); } function alertNewVideo(newID){ let text = "A new video of yours has been published.\nGo to My Videos?"; let url = "/my/videos/"; if (confirm(text)) { window.location.href = url; } } function updateLastVideoData(minutes = 30){ const waitTime = minutes * 60; let ageOfCheck = lastVideoDataAge(refreshVideosMinutes); // let ageOfCheck = 31*60; // console.log("seconds passed:",ageOfCheck,"\nwaitTime:",waitTime,"\n") let minutesOfAge = Math.round(ageOfCheck / 60); if(ageOfCheck > waitTime){ saveLastVideoID(function(lastID, newID) { // console.log("lastID:",lastID,"\nnewID:",newID) if(newID && lastID && lastID !== newID){ alertNewVideo(newID); }else{ console.log("No new videos were published") // console.log("Still the same video ("+lastID,"==",newID+")") } }); } else { console.log("Only", minutesOfAge, "minutes have passed,",(minutes - minutesOfAge), "to go"); } } // console.log("notifyProcessedVideos:",notifyProcessedVideos) if(notifyProcessedVideos){ updateLastVideoData(refreshVideosMinutes); } function contryCodesArray(){ return { "Andorra": "ad", "United Arab Emirates": "ae", "Afghanistan": "af", "Antigua and Barbuda": "ag", "Anguilla": "ai", "Albania": "al", "Armenia": "am", "Angola": "ao", "Antarctica": "aq", "Argentina": "ar", "American Samoa": "as", "Austria": "at", "Australia": "au", "Aruba": "aw", "Åland Islands": "ax", "Azerbaijan": "az", "Bosnia and Herzegovina": "ba", "Barbados": "bb", "Bangladesh": "bd", "Belgium": "be", "Burkina Faso": "bf", "Bulgaria": "bg", "Bahrain": "bh", "Burundi": "bi", "Benin": "bj", "Saint Barthélemy": "bl", "Bermuda": "bm", "Brunei": "bn", "Bolivia": "bo", "Caribbean Netherlands": "bq", "Brazil": "br", "Bahamas": "bs", "Bhutan": "bt", "Bouvet Island": "bv", "Botswana": "bw", "Belarus": "by", "Belize": "bz", "Canada": "ca", "Cocos (Keeling) Islands": "cc", "DR Congo": "cd", "Central African Republic": "cf", "Republic of the Congo": "cg", "Switzerland": "ch", "Côte d'Ivoire (Ivory Coast)": "ci", "Cook Islands": "ck", "Chile": "cl", "Cameroon": "cm", "China": "cn", "Colombia": "co", "Costa Rica": "cr", "Cuba": "cu", "Cape Verde": "cv", "Curaçao": "cw", "Christmas Island": "cx", "Cyprus": "cy", "Czechia": "cz", "Germany": "de", "Djibouti": "dj", "Denmark": "dk", "Dominica": "dm", "Dominican Republic": "do", "Algeria": "dz", "Ecuador": "ec", "Estonia": "ee", "Egypt": "eg", "Western Sahara": "eh", "Eritrea": "er", "Spain": "es", "Ethiopia": "et", "European Union": "eu", "Finland": "fi", "Fiji": "fj", "Falkland Islands": "fk", "Micronesia": "fm", "Faroe Islands": "fo", "France": "fr", "Gabon": "ga", "United Kingdom": "gb", "England": "gb-eng", "Northern Ireland": "gb-nir", "Scotland": "gb-sct", "Wales": "gb-wls", "Grenada": "gd", "Georgia": "ge", "French Guiana": "gf", "Guernsey": "gg", "Ghana": "gh", "Gibraltar": "gi", "Greenland": "gl", "Gambia": "gm", "Guinea": "gn", "Guadeloupe": "gp", "Equatorial Guinea": "gq", "Greece": "gr", "South Georgia": "gs", "Guatemala": "gt", "Guam": "gu", "Guinea-Bissau": "gw", "Guyana": "gy", "Hong Kong": "hk", "Heard Island and McDonald Islands": "hm", "Honduras": "hn", "Croatia": "hr", "Haiti": "ht", "Hungary": "hu", "Indonesia": "id", "Ireland": "ie", "Israel": "il", "Isle of Man": "im", "India": "in", "British Indian Ocean Territory": "io", "Iraq": "iq", "Iran": "ir", "Iceland": "is", "Italy": "it", "Jersey": "je", "Jamaica": "jm", "Jordan": "jo", "Japan": "jp", "Kenya": "ke", "Kyrgyzstan": "kg", "Cambodia": "kh", "Kiribati": "ki", "Comoros": "km", "Saint Kitts and Nevis": "kn", "North Korea": "kp", "South Korea": "kr", "Kuwait": "kw", "Cayman Islands": "ky", "Kazakhstan": "kz", "Laos": "la", "Lebanon": "lb", "Saint Lucia": "lc", "Liechtenstein": "li", "Sri Lanka": "lk", "Liberia": "lr", "Lesotho": "ls", "Lithuania": "lt", "Luxembourg": "lu", "Latvia": "lv", "Libya": "ly", "Morocco": "ma", "Monaco": "mc", "Moldova": "md", "Montenegro": "me", "Saint Martin": "mf", "Madagascar": "mg", "Marshall Islands": "mh", "North Macedonia": "mk", "Mali": "ml", "Myanmar": "mm", "Mongolia": "mn", "Macau": "mo", "Northern Mariana Islands": "mp", "Martinique": "mq", "Mauritania": "mr", "Montserrat": "ms", "Malta": "mt", "Mauritius": "mu", "Maldives": "mv", "Malawi": "mw", "Mexico": "mx", "Malaysia": "my", "Mozambique": "mz", "Namibia": "na", "New Caledonia": "nc", "Niger": "ne", "Norfolk Island": "nf", "Nigeria": "ng", "Nicaragua": "ni", "Netherlands": "nl", "Norway": "no", "Nepal": "np", "Nauru": "nr", "Niue": "nu", "New Zealand": "nz", "Oman": "om", "Panama": "pa", "Peru": "pe", "French Polynesia": "pf", "Papua New Guinea": "pg", "Philippines": "ph", "Pakistan": "pk", "Poland": "pl", "Saint Pierre and Miquelon": "pm", "Pitcairn Islands": "pn", "Puerto Rico": "pr", "Palestine": "ps", "Portugal": "pt", "Palau": "pw", "Paraguay": "py", "Qatar": "qa", "Réunion": "re", "Romania": "ro", "Serbia": "rs", "Russia": "ru", "Rwanda": "rw", "Saudi Arabia": "sa", "Solomon Islands": "sb", "Seychelles": "sc", "Sudan": "sd", "Sweden": "se", "Singapore": "sg", "Saint Helena, Ascension and Tristan da Cunha": "sh", "Slovenia": "si", "Svalbard and Jan Mayen": "sj", "Slovakia": "sk", "Sierra Leone": "sl", "San Marino": "sm", "Senegal": "sn", "Somalia": "so", "Suriname": "sr", "South Sudan": "ss", "São Tomé and Príncipe": "st", "El Salvador": "sv", "Sint Maarten": "sx", "Syria": "sy", "Eswatini (Swaziland)": "sz", "Turks and Caicos Islands": "tc", "Chad": "td", "French Southern and Antarctic Lands": "tf", "Togo": "tg", "Thailand": "th", "Tajikistan": "tj", "Tokelau": "tk", "Timor-Leste": "tl", "Turkmenistan": "tm", "Tunisia": "tn", "Tonga": "to", "Turkey": "tr", "Trinidad and Tobago": "tt", "Tuvalu": "tv", "Taiwan": "tw", "Tanzania": "tz", "Ukraine": "ua", "Uganda": "ug", "United States Minor Outlying Islands": "um", "United Nations": "un", "United States": "us", "Uruguay": "uy", "Uzbekistan": "uz", "Vatican City (Holy See)": "va", "Saint Vincent and the Grenadines": "vc", "Venezuela": "ve", "British Virgin Islands": "vg", "United States Virgin Islands": "vi", "Vietnam": "vn", "Vanuatu": "vu", "Wallis and Futuna": "wf", "Samoa": "ws", "Kosovo": "xk", "Yemen": "ye", "Mayotte": "yt", "South Africa": "za", "Zambia": "zm", "Zimbabwe": "zw"} } })();