// ==UserScript==
// @name Camwhores.tv Utilities Mod
// @namespace https://sleazyfork.org/users/1281730-vipprograms
// @version 1.9.0
// @description Info preview, removal of lock from friends' vidoes, restored upload button, and more.
// @author vipprograms
// @match https://www.camwhores.tv/*
// @exclude *.camwhores.tv/*mode=async*
// @grant GM_xmlhttpRequest
// @grant GM.getValue
// @grant GM_getValue
// @grant GM.setValue
// @grant GM_setValue
// @grant GM_registerMenuCommand
// @grant GM.registerMenuCommand
// @grant GM_addStyle
// @grant GM_download
// @grant GM_openInTab
// @grant window.close
// @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAMUExURQAAAP8ANwwA/////7gbQJkAAAABdFJOUwBA5thmAAAAAWJLR0QDEQxM8gAAAAd0SU1FB+gDHhIuCjXV/h8AAAA4SURBVAjXY2ANDQ1gEA0NDWEIYWBgZAhgAAIUghEiC1YHBhpMDRpIhBbXghUMXKtWLWBgWqHVAACjlwz/pN0YPwAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyNC0wMy0zMFQxODo0NjowOSswMDowME+iXNIAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjQtMDMtMzBUMTg6NDY6MDkrMDA6MDA+/+RuAAAAKHRFWHRkYXRlOnRpbWVzdGFtcAAyMDI0LTAzLTMwVDE4OjQ2OjEwKzAwOjAwMNiA/AAAAABJRU5ErkJggg==
// @require https://cdn.jsdelivr.net/npm/@violentmonkey/shortcut@1
// @require https://code.jquery.com/jquery-3.7.1.slim.min.js
// ==/UserScript==
(function() {
'use strict';
var _GM_registerMenuCommand, _GM_notification, options, optionName;
const refreshVideosMinutes = 30;
const { register } = VM.shortcut;
const currentVersion = GM_info.script.version;
const currentDate = new Date();
const metaPage = "https://update.sleazyfork.org/scripts/491272/Camwhorestv%20Utilities%20Mod.meta.js";
VM.shortcut.register('c-i', () => {
console.log('You just pressed Ctrl-I');
});
function isArrayEmpty(arr) {
return arr.length === 0;
}
function retrieveValueFromStorage(key) {
if (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(optionName, defaultValue = false){
var updatedOptions;
let options = retrieveValueFromStorage("options");
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:";
const alternative_thumbnails_users_default = ['deathstar45'];
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
optionName = "alternative thumbnails";
toggleChange(optionName, true)
var altThumbs = retrieveValueFromStorage("options")[optionName];
optionName = "restore upload button";
toggleChange(optionName, true)
var restoreUploadButton = retrieveValueFromStorage("options")[optionName];
optionName = "notify me of processed videos";
toggleChange(optionName, false)
var notifyProcessedVideos = retrieveValueFromStorage("options")[optionName];
let updateRemindersOptionName = "update reminders";
toggleChange(updateRemindersOptionName, true)
var updateReminders = retrieveValueFromStorage("options")[updateRemindersOptionName];
const style = document.createElement('style');
// custom CSS
style.textContent = `
a.button{color:#4e4e4e !important;}ul > li.next, ul > li.prev {display: list-item !important;}.item:hover > a > div.img > .friends-tag, .item:hover > a > div.img > .videos-tag{background-color:#1a1a1a !important;}.button{color: rgb(183, 176, 167);text-align: center;border: 1px solid transparent;font-size: 14px;padding: 5px 10px;cursor: pointer;background: linear-gradient(to bottom, #ffffff 0%, #cccccc 100%);border-radius: 3px;display: inline-block;margin: 0 .3rem .3rem 0;color: dimgrey;}.button:hover{color: #f56c08 !important;border: 1px solid transparent;background: #1e1e1e;}div.img span.unread-notification{background: #c45606ab;backdrop-filter: blur(5px) brightness(1);top: 0px;left: 0px;border-bottom-left-radius: 3px;border-bottom-right-radius: 3px;outline: 3px solid #f56c08;animation: glow 5s infinite;}@keyframes glow {0% {outline-color: #f56c08d6;}50% {outline-color: transparent;}100% {outline-color: #f56c08d6;}}.form-container {box-sizing: border-box;position: fixed;top: 50%;left: 50%;transform: translate(-50%, -50%);max-width: 100vw;width: 800px;padding: 2.5rem;border-radius: .25rem;z-index:99999;background-color: transparent !important;backdrop-filter: blur(1rem) brightness(.8) contrast(1.2) }.form-container * {box-sizing: inherit;}.textarea-input {width: 100%;min-height: 10rem;padding: 1rem;border-radius: .25rem;color-scheme: dark !important;}.buttons-line {margin-top: .3rem;gap:.3rem;width: 100%;display: flex;}.submit-button:hover, .cancel-button:hover{filter: brightness(.8) contrast(1.2) }.submit-button, .cancel-button{transform: .3s;}.submit-button {height: 50px;flex-grow: 1;cursor: pointer;border-radius: .25rem;color-scheme: dark !important;font-weight:bold;border:0;}.cancel-button {width:min-content;height: 50px;cursor: pointer;border-radius: .25rem;color-scheme: dark !important;background-color: red;font-weight:bold;padding-inline:.5rem;border:0;}input.accept-button, span.accept-button {color: #fff;background-image: linear-gradient(rgb(0, 128, 0) 0%, rgb(0, 255, 0) 100%);}input.accept-button:hover, span.accept-button:hover {color: #fff !important;background-image: linear-gradient(rgb(34, 139, 34) 0%, rgb(50, 205, 50) 100%) !important;}input.reject-button, span.reject-button {color: #fff;background-image: linear-gradient(rgb(255, 0, 0) 0%, rgb(128, 0, 0) 100%);}input.reject-button:hover, span.reject-button:hover {color: #fff !important;background-image: linear-gradient(rgb(220, 20, 60) 0%, rgb(178, 34, 34) 100%) !important;}#vid_previews {display: flex;flex-wrap: nowrap;height: 135px;margin-block: .5rem;gap: 5px;box-sizing: border-box;}#vid_previews .img-div {width:185px;height:100%;position: relative;box-sizing: inherit;}.list-messages .added {position: absolute;right: 0;}.list-messages .item {margin-right: 0;}#vid_previews .img-div img{box-sizing: inherit;width: 100%;height:100%;}#vid_previews .img-div h2{position: absolute;bottom: 0;background-color: rgb(0 0 0 / 65%);font-size: 1rem;line-height: 1.2rem;backdrop-filter: blur(5px);color: rgb(196 196 196);width: 100%;word-wrap: break-word;box-sizing: inherit;text-align: center;}.bottom-element{margin-top: 1em;margin-bottom: 1em;}form .bottom{padding-top: .5rem;}form .bottom .submit{float: initial;height: auto;padding: .45rem .5rem;margin: 0;}.margin-fix .bottom{margin:0;}#gen_joined_text{margin: .5rem 0 .25rem 0;}a[href="http://flowplayer.org"], a[class="fp-brand"]{opacity: 0 !important;pointer-events: none !important;}div.block-profile > div > div > div.about-me > div > em{white-space:pre;}
h1.online:after{
content: '';
height: .45rem;
aspect-ratio: 1;
display: inline-block;
background-color: green;
position: relative;
left: .5rem;
border-radius: 50%;
bottom: .1rem;
}
div.block-profile > div > div > div.about-me > div{
width: 100%;
box-sizing: border-box;
}
div.block-profile > div > div > div.about-me > div>em{
width: 100%;
display: inline-block;
word-break: auto-phrase;
word-wrap: break-word;
box-sizing: border-box;
text-wrap: pretty;
}
.user-search {
float: right;
/*min-width: 140px;*/
position: relative;
margin-left: 3px;
cursor: pointer;
background: #f1f1f1;
background: linear-gradient(to bottom, #f1f1f1 0%, #d8d8d8 100%);
border-radius: 2px;
padding:0;
}
.user-search strong {
display: block;
font-size: 12px;
line-height: 15px;
padding: 5px 12px 5px 28px;
white-space: nowrap;
color: #4e4e4e;
cursor: pointer;
max-width: 200px;
overflow: hidden;
}
.user-search .type-search {
background: url('https://shrph.altervista.org/img/search.png') 5px 4px no-repeat;
}
.user-search .icon {
display: block;
position: absolute;
width: 100%;
height: 100%;
top:0;
}
#tab_screenshots > div > .item,
#tab_screenshots > div > .item > .img {
width: 250px;
height: auto;
}
#tab_screenshots > div > .item > .img {
}
`;
document.head.appendChild(style);
function makeValidUrlString(inputString) {
var validString = inputString.replace(/[^\w\s\/-]/g, ''); // Remove special characters
validString = validString.replace(/[-_]{2,}/g, '-'); // Turn consecutive underscores or hyphens into single hyphens
validString = validString.replace(/\s+/g, '-'); // Turn spaces into hyphens
validString = validString.replace(/\//g, '-'); // Turn slashes into hyphens
return validString;
}
function friendRequestSetup(video_title, video_url, userID){
var vid_code = video_url.replace("https://www.camwhores.tv/videos/", "");
var parts = vid_code.split("/");
var videoId = parts[0];
var code = parts[1];
let cumData = {
title: video_title,
videoId: videoId,
userId: userID
};
let lastCumVideoAdd = JSON.parse(localStorage.getItem('last_cum_video_data')) || {};
lastCumVideoAdd[userID] = cumData;
localStorage.setItem('last_cum_video_data', JSON.stringify(lastCumVideoAdd));
}
function convertToSeconds(timeString) {
let [_, value, unit] = timeString.match(/(\d+) (\w+)/);
value = parseInt(value);
switch (unit) {
case 'second':
case 'seconds':
return value;
case 'minute':
case 'minutes':
return value * 60;
case 'hour':
case 'hours':
return value * 3600;
case 'day':
case 'days':
return value * 86400;
case 'week':
case 'weeks':
return value * 604800;
case 'month':
case 'months':
return value * 2592000; // assuming 30 days per month
case 'year':
case 'years':
return value * 31536000; // assuming 365 days per year
default:
return 0;
}
}
function fetchAndParseHTML(url, callback) {
GM_xmlhttpRequest({
method: "GET",
url: url,
onload: function(response) {
var parser = new DOMParser();
var htmlDoc = parser.parseFromString(response.responseText, "text/html");
callback(htmlDoc);
}
});
}
function fetchAndExtract(url, callback) {
GM_xmlhttpRequest({
method: "GET",
url: url,
onload: function(response) {
document.evaluate('//*[@id="list_messages_my_conversation_messages_items"]/div/div[3]/img', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue?.remove();
var parser = new DOMParser();
var htmlDoc = parser.parseFromString(response.responseText, "text/html");
callback(htmlDoc);
}
});
}
/*
usage:
fetchAndExtract(messageUrl, function(htmlDoc) {
});
*/
function getAllSessionStorage() {
var sessionStorageItems = {};
for (var i = 0; i < sessionStorage.length; i++) {
var key = sessionStorage.key(i);
var value = sessionStorage.getItem(key);
sessionStorageItems[key] = value;
}
return sessionStorageItems;
}
function getCurrentPage(){
var allSessionStorage = getAllSessionStorage();
var paramsStorageKey = Object.keys(allSessionStorage).find(key => key.endsWith(":params"));
if(!allSessionStorage || !paramsStorageKey){
return 1;
}
// console.log(allSessionStorage)
// console.log("paramsStorageKey:",paramsStorageKey)
var paramsValue = JSON.parse(allSessionStorage[paramsStorageKey]).from_my_conversations;
// console.log("getCurrentPage:",paramsValue)
if(!paramsValue){
return 1;
}
let int = parseInt(paramsValue, 10);
// console.log(int)
return int;
}
function setUploadButtonTimestamp(){
var timestamp = Date.now();
var jsonData = JSON.stringify(timestamp);
localStorage.setItem('UploadButtonTimestamp', jsonData);
}
function getCookie(name) {
let cookieArr = document.cookie.split("; ");
for(let cookie of cookieArr) {
let [key, value] = cookie.split("=");
if(key === name) return value;
}
return null;
}
function loadArrayLocalStorage(name='lastVideoData') {
var jsonData = localStorage.getItem(name);
if (!jsonData) {
return [];
}
var data = JSON.parse(jsonData);
return data;
}
function saveArrayLocalStorage(name='lastVideoData', data){
var timestamp = Date.now();
var jsonData = JSON.stringify(data);
localStorage.setItem(name, jsonData);
}
function getNewUID() {
let sessionStorageData = getAllSessionStorage();
if(!sessionStorageData){
return null;
}
for (let key in sessionStorageData) {
let matches = key.match(/^(\d+):https:\/\/www\.camwhores\.tv/);
if (matches) {
return matches[1];
}
}
return null;
}
function saveUID(){
let uid = getNewUID();
if(uid){
let current_kt = getCookie("kt_member");
let data = {uid: uid, kt: current_kt};
saveArrayLocalStorage("cum_user_id", data);
return uid;
}
return
}
function silentUidUpdater(){
let uidArray = loadArrayLocalStorage("cum_user_id");
if(!uidArray || getCookie("kt_member") !== uidArray.kt){
saveUID();
}
}
function currentUserID(){
let current_kt = getCookie("kt_member");
let uidArray = loadArrayLocalStorage("cum_user_id");
if(uidArray && uidArray.kt === current_kt){
return uidArray.uid;
}else{
return saveUID()
}
return
}
async function getResponseStatus(url) {
try {
let response = await fetch(url, { method: 'HEAD' });
return response.status;
} catch (error) {
return null;
}
}
function secondsSinceTimestamp(timestamp){
return (Date.now() - timestamp) / 1000;
}
let currentUID = currentUserID();
// console.log("User ID:", currentUID, "(https://www.camwhores.tv/members/" + currentUID + "/)")
silentUidUpdater()
function uploadRestored(){
alert("The upload button has been restored!")
localStorage.removeItem("UploadButtonTimestamp");
}
// UPLOAD button
const nav = document.querySelector('.navigation .primary');
let lastCheck = localStorage.getItem("UploadButtonTimestamp"); // EXAMPLE: "1717655623061"
let minutesSinceLastCheck = secondsSinceTimestamp(lastCheck) / 60;
let roundedMinutes = Math.floor(minutesSinceLastCheck);
if (nav && restoreUploadButton && ![...nav.querySelectorAll('a')].some(link => link.textContent.trim().includes('Upload'))) {
const uploadLink = document.createElement('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();
}
}
});
});
if(lastCheck && minutesSinceLastCheck > 30){
getResponseStatus(uploadURL).then(status => {
if (status === 200) {
uplaodRestored();
} else {
console.log("Upload button still unavailable. Last check",minutesSinceLastCheck,"minutes ago")
setUploadButtonTimestamp();
}
});
}else{
// console.log("Only",roundedMinutes, "minutes have passed since last upload button check,", 30 - roundedMinutes, "to go");
}
}else{
// console.log("Couldn't/shouldn't restoreUploadButton", restoreUploadButton)
if(lastCheck){
uploadRestored()
}
}
if ((window.location.href.endsWith("?action=reject_add_to_friends_done")) ||
(window.location.href.endsWith("?action=confirm_add_to_friends_done"))) {
let urlOfUser = document.querySelector('#list_messages_my_conversation_messages > div.headline > h2 > a:nth-child(2)')
let username = urlOfUser.innerHTML.trim();
let userID = urlOfUser.getAttribute('href').match(/\/(\d+)\//)[1];
const storedData = JSON.parse(localStorage.getItem('closedWindow'));
if (storedData) {
let { uid, timestamp } = storedData;
let currentTime = Date.now();
let timeDifference = (currentTime - timestamp) / 1000; // in seconds
console.log(timeDifference + " seconds, uid: "+userID+" vs "+uid)
if (timeDifference < 30 && userID == uid) {
console.log(`Less than 30 seconds have passed since window closed. User ID: ${uid}`);
window.close();
}else{
}
}
}else if (window.location.href == "https://www.camwhores.tv/my/messages/") {
function myMessagesAsyncURL(pageInt=1){
const utcTimestamp = new Date().getTime();
const pageID = pageInt.toString();
return "https://www.camwhores.tv/my/messages/?mode=async&function=get_block&block_id=list_members_my_conversations&sort_by=added_date&from_my_conversations="+pageID+"&_="+utcTimestamp;
}
// console.log(myMessagesAsyncURL())
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{
hasNewElements = true;
}
});
if (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 = '↻'; // 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/")) {
// VM.shortcut.register('c-enter', () => {
// console.log('You just pressed Ctrl-I');
// });
function updateButtonStyle(button, state) {
if (state && button) {
button.classList.add("accept-button");
} else if(button) {
button.classList.add("reject-button");
// console.log(button)
}else{
// console.log(button + " button absent")
}
}
let textarea = document.querySelector("#send_message_message");
let divTextarea = document.createElement('div');
let urlOfUser = document.querySelector('#list_messages_my_conversation_messages > div.headline > h2 > a:nth-child(2)')
let username = urlOfUser.innerHTML.trim();
let userID = urlOfUser.getAttribute('href').match(/\/(\d+)\//)[1];
let confirmButton = document.querySelector('input[name="confirm"]');
let rejectButton = document.querySelector('input[name="reject"]');
let buttonsParent = confirmButton ? confirmButton.parentElement : null;
let confirmClose = null
let denyClose = null
// console.log(userID)
document.querySelector('input.submit').addEventListener('click', function() {
divTextarea.innerHTML = '';
});
$(document).ready(function() {
$(document).keyup(function(event) {
if (event.ctrlKey && event.key === 'Enter') {
event.preventDefault();
// alert("Submitting");
$("#send_message_form").submit();
}
});
});
function copyContentToTextarea() {
const tempDiv = document.createElement('div');
tempDiv.innerHTML = divTextarea.innerHTML;
const content = [];
tempDiv.childNodes.forEach(node => {
if (node.nodeType === 3) { // Text node
content.push(node.textContent);
} else if (node.nodeType === 1 && node.tagName === 'IMG') { // Image node
content.push(node.alt);
}
});
const finalText = content.join('').trim(); // Join text content and alt attributes with space
textarea.value = finalText; // Set the final text to the textarea
}
textarea.style.display = "none";
divTextarea.innerHTML = textarea.value;
divTextarea.contentEditable = true;
divTextarea.style.minHeight = "5rem";
divTextarea.style.resize = "vertical";
divTextarea.style.overflow = "auto";
divTextarea.style.fontSize = "14px";
divTextarea.classList.add("textarea");
textarea.parentNode.insertBefore(divTextarea, textarea.nextSibling);
document.querySelectorAll('.smileys-bar img').forEach(function(img) {
img.addEventListener('click', function(event) {
event.preventDefault();
event.stopPropagation();
var imgClone = img.cloneNode(true);
imgClone.style.cursor = "auto"; // Add cursor style
divTextarea.appendChild(imgClone);
copyContentToTextarea()
return false;
});
});
divTextarea.addEventListener('input', copyContentToTextarea);
var inlineTexts = document.querySelectorAll('span.inline-text, span.original-text');
inlineTexts.forEach(function(span) {
var lineText = span.textContent.trim();
if (lineText.includes('##')) {
var index = lineText.indexOf(':');
var videoText = lineText.substring(0, index).trim();
var videoInfo = lineText.substring(index + 1).trim().replace('##', '');
let parts = videoInfo.split("\n");
let videoCode = parts[0];
let videoID = parts[1];
let url = 'https://www.camwhores.tv/videos/' + videoID + "/" + makeValidUrlString(videoCode) + '/';
// console.log(url)
fetch(url)
.then(response => {
if (response.ok) {
span.innerHTML = videoText + ': <a href="' + url + '" class="toggle-button" style="display:inline-block">'+videoCode+'</a>';
} else if (response.status === 404) {
console.log("URL is 404");
} else {
console.error("Error:", response.status);
}
})
.catch(error => console.error("Error:", error));
// span.innerHTML = videoText + ': <a href="' + url + '" class="toggle-button" style="display:inline-block">Open video</a>';
}
});
function andClosePage(){
const closedWindow = {
uid: userID,
timestamp: Date.now()
};
localStorage.setItem('closedWindow', JSON.stringify(closedWindow));
console.log("Window should close now")
window.close();
}
function addCloseButtonsListeners(confirmButton, rejectButton) {
var confirmClose, denyClose;
if (confirmButton) {
var buttonsParent = confirmButton.parentElement;
confirmClose = document.createElement('span');
confirmClose.className = 'submit button';
confirmClose.innerHTML = 'Confirm & Close';
denyClose = document.createElement('span');
denyClose.className = 'submit button';
denyClose.innerHTML = 'Deny & Close';
confirmClose.addEventListener('click', function(event) {
event.preventDefault();
// alert("Clicked! (when done debugging, REMOVE and CLOSE)")
confirmButton.click();
andClosePage()
});
denyClose.addEventListener('click', function(event) {
event.preventDefault();
// alert("Clicked! (when done debugging, REMOVE and CLOSE)")
rejectButton.click();
andClosePage()
});
var closeButtonsContainer = document.createElement('div');
closeButtonsContainer.classList.add('closeInputs');
buttonsParent.appendChild(confirmClose);
buttonsParent.appendChild(document.createTextNode(' '));
buttonsParent.appendChild(denyClose);
buttonsParent.appendChild(closeButtonsContainer);
confirmButton.style.width = confirmClose.offsetWidth + 'px';
rejectButton.style.width = denyClose.offsetWidth + 'px';
}
return {
confirmClose: confirmClose,
denyClose: denyClose
};
}
function updateMessageDOM(htmlDoc, confirmClose, denyClose) {
const twoYearsSeconds = 60 * 60 * 24 * 365 * 2;
var titleText = htmlDoc.querySelector('#list_videos_uploaded_videos > div:nth-child(1) > h2')?.textContent.trim();
var lastUploadTime = htmlDoc.querySelector('#list_videos_uploaded_videos_items > div.item > a > div.wrap > div.added > em')?.textContent.trim();
var joinedDateText = htmlDoc.querySelector('div.block-profile > div.profile-list > div.margin-fix > div.column > div:nth-child(3) > em')?.textContent.trim();
var lastLogin = htmlDoc.querySelector('div.block-profile > div.profile-list > div.margin-fix > div.last-login > div.item')?.textContent.trim();
let secondsSinceOnline = convertToSeconds(lastLogin);
let recentlyOnline = secondsSinceOnline <= 300;
// let recentlyOnline = true;
const headlineH2 = document.querySelector('#list_messages_my_conversation_messages .headline h2');
console.log("recentlyOnline:", recentlyOnline);
var recentlyUploaded = false;
if(!document.hasFocus() && !titleText){
denyClose.click()
window.close();
}
if(lastUploadTime){
let lastUploadTimeSeconds = convertToSeconds(lastUploadTime);
recentlyUploaded = lastUploadTimeSeconds < twoYearsSeconds;
}
if(recentlyOnline){
GM_addStyle(`.list-messages .item.new .added:after {
background-color: green;
}`);
document.querySelector("#list_messages_my_conversation_messages_items > div.item.new > div.added").textContent += " (online)";
headlineH2.innerHTML += " (online)"
}
if (titleText && recentlyUploaded) { // THERE ARE VIDEOS and RECENT
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 = `${extractedTitle[1]} videos, last ${lastUploadTime}<br>Joined ${joinedDateText}`;
var messageDiv = document.querySelector('#list_messages_my_conversation_messages_items > div > div:nth-child(3)');
if (messageDiv) {
messageDiv.appendChild(generatedTextDiv);
}
}
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 secondsSinceOnline = convertToSeconds(lastLogin);
let recentlyOnline = secondsSinceOnline <= 300;
let h1 = document.querySelector("h1");
const country = document.querySelector('div.block-profile > div.profile-list > div.margin-fix > div.column > div:nth-child(1) > em');
const countryName = country.textContent.trim()
let countryCode = contryCodesArray()[countryName] || [];
const parent = document.querySelector('div.block-profile > div.profile-list > div.margin-fix > div.column > div:nth-child(1)');
function addSearchButton(){
let sortElement = document.querySelector("#list_videos_uploaded_videos > div.headline > div.sort");
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")) {
var userVideoData,lastCumTitle,lastVidCode,lastUserID;
let addButton = document.querySelector('a[href="#friends"][data-action="add_to_friends"]');
let textarea = document.getElementById('add_to_friends_message');
// let 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_data')) || {};
// console.log(retrievedData);
if (retrievedData[userId]) {
userVideoData = retrievedData[userId];
console.log(userVideoData);
lastCumTitle = userVideoData.title;
lastVidCode = userVideoData.videoId;
lastUserID = userVideoData.userId;
} else {
console.log("No data found for this user.");
}
let pageTitle = document.title;
let username = pageTitle.replace("'s Page", "");
if (textarea !== null && !addButton.classList.contains('done') && username !== lastAutoFriend && lastCumTitle !== null && addButton !== null) {
textarea.value = "";
if(userId === lastUserID){
textarea.value += friend_request_text + " " + lastCumTitle + "\n##" + lastVidCode;
}
document.querySelector('input[type="submit"].submit[value="Invite"]').click();
localStorage.setItem('last_auto_friend', username);
addButton.click(); // final submit button
}
// console.log("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));
}
function waitForElementExists(parent, selector) {
return new Promise((resolve, reject) => {
const observer = new MutationObserver((mutations, me) => {
const element = parent.querySelector(selector);
if (element) {
resolve(element);
me.disconnect();
}
});
observer.observe(parent, {
childList: true,
subtree: true
});
});
}
function addDownloadLink(video) {
const url = video.getAttribute('src');
const name = document.querySelector('.headline').innerText + '.mp4';
// Check if the download link already exists
if (document.getElementById('downloadVideoLink')) return;
// Create the download link
const link = document.createElement('a');
link.id = 'downloadVideoLink';
link.innerText = 'Download';
link.href = url;
link.download = name;
link.classList = "toggle-button";
const li = document.createElement('li');
li.appendChild(link);
const ul = document.querySelector('div.video-holder > div.video-info > div > div.info-buttons > div.tabs-menu > ul');
ul.insertBefore(li, ul.firstChild);
}
waitForElementExists(document.body, 'video')
.then(video => addDownloadLink(video))
.catch(error => console.error('Error:', error));
}
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;
}
});
}
if(window.location.href.startsWith("https://www.camwhores.tv/edit-video/")){
document.querySelector('.section-title.expand[data-expand-id="tab_screenshots"]').click();
const elements = document.querySelectorAll("#tab_screenshots > div > div:nth-child(-n+5) > div.item-control > div.item-control-holder");
elements.forEach(element => {
element.addEventListener('click', () => {
document.querySelector('input.submit[value="Save"]').click();
if (history.length === 1) {
window.close();
}
});
});
// console.log("history.length:",history.length)
}
} // end of (NOT "/my/videos/")
if (window.location.href === "https://www.camwhores.tv/my/") {
// console.log("HELLO PROFILE")
let profileCSS = document.createElement('style');
profileCSS.className = "profile-css";
profileCSS.textContent = `
#edit_profile_about_me{
height:225px;
}
strong.popup-title,
span.selection [role="combobox"]{
display:none;
}
body > div.fancybox-overlay.fancybox-overlay-fixed > div{
top:0 !important;
height: 100svh !important;
}
body > div.fancybox-overlay.fancybox-overlay-fixed,
body > div.fancybox-overlay.fancybox-overlay-fixed > *{
box-sizing: border-box;
}
div.fancybox-inner{
height:100% !important;
width: max-content !important;
}
.fancybox-close{
top:9px !important;
}
`;
document.head.appendChild(profileCSS);
}
// ANY PAGE
function myVideosAsyncURL(pageInt){
const utcTimestamp = new Date().getTime();
const pageID = pageInt.toString();
return "https://www.camwhores.tv/my/videos/?mode=async&function=get_block&block_id=list_videos_my_uploaded_videos&sort_by=&from_my_videos="+pageID+"&_="+utcTimestamp;
}
/* fetchAndParseHTML("https://www.camwhores.tv/my/", function(htmlDoc) {
console.log(htmlDoc)
});*/
function pagesLastProcessedVideo(page, callback) {
fetchAndParseHTML(myVideosAsyncURL(page), function(htmlDoc) {
const videoItems = htmlDoc.querySelectorAll("#list_videos_my_uploaded_videos_items > form > div.item.private");
let lastProcessingIndex = -1;
for (let i = videoItems.length - 1; i >= 0; i--) {
if (videoItems[i].classList.contains('processing')) {
lastProcessingIndex = i;
break;
}
}
if (lastProcessingIndex !== -1 && lastProcessingIndex < videoItems.length - 1) {
const precedingItem = videoItems[lastProcessingIndex + 1];
const checkbox = precedingItem.querySelector(".item-control-holder .toggle-button input[type='checkbox']");
if (checkbox) {
callback(checkbox.value);
return;
}
}
callback(false);
});
}
function lastProcessedVideoID(callback) {
var found = false;
var completedIterations = 0;
let maxPages = 3;
for (var pageN = 1; pageN <= maxPages; pageN++) {
(function(page) {
pagesLastProcessedVideo(page, function(checkboxValue) {
completedIterations++; // Increment the counter for each completed iteration
if (checkboxValue && !found) {
found = true;
callback(checkboxValue);
} else if (completedIterations === maxPages && !found) { // Check if all iterations have completed and no checkbox value is found
callback(false);
}
});
})(pageN);
}
}
function loadLastVideoData() {
var jsonData = localStorage.getItem('lastVideoData');
if (!jsonData) {
return [null, null]; // No stored data, return null values
}
var data = JSON.parse(jsonData);
return data;
}
function lastVideoDataAge(refreshMinutes=30) {
var data = loadLastVideoData();
if (!data[1]) { // Timestamp
console.log("Force recheck")
var bigTime = (refreshMinutes * 60) + 1;
// bigTime = 0;
return bigTime; // No stored timestamp, assume age is 0 seconds
}
var timestamp = data[1];
var currentTime = Date.now();
var elapsedTimeSeconds = (currentTime - timestamp) / 1000;
return elapsedTimeSeconds;
}
function saveLastVideoID(callback) {
const lastID = loadLastVideoData()[0];
lastProcessedVideoID(function(currentID) {
var timestamp = Date.now();
var data = [currentID, timestamp]; // Include lastID and currentID in the data array
var jsonData = JSON.stringify(data);
localStorage.setItem('lastVideoData', jsonData);
callback(lastID, currentID); // Invoke the callback with both lastID and currentID
console.log("Last ID:", lastID, "\nCurrent ID:", currentID, "(https://www.camwhores.tv/edit-video/"+currentID+"/)");
});
}
function alertNewVideo(newID){
let text = "A new video of yours has been published.\nGo to My Videos?";
let url = "/my/videos/";
if (confirm(text)) {
window.location.href = url;
}
}
function updateLastVideoData(minutes = 30){
const waitTime = minutes * 60;
let ageOfCheck = lastVideoDataAge(refreshVideosMinutes);
// let ageOfCheck = 31*60;
// console.log("seconds passed:",ageOfCheck,"\nwaitTime:",waitTime,"\n")
let minutesOfAge = Math.round(ageOfCheck / 60);
if(ageOfCheck > waitTime){
saveLastVideoID(function(lastID, newID) {
// console.log("lastID:",lastID,"\nnewID:",newID)
if(newID && lastID && lastID !== newID){
alertNewVideo(newID);
}else{
console.log("No new videos were published")
// console.log("Still the same video ("+lastID,"==",newID+")")
}
});
} else {
// console.log("Only",minutesOfAge, "minutes have passed since updateLastVideoData,",(minutes - minutesOfAge), "to go");
}
}
// console.log("notifyProcessedVideos:",notifyProcessedVideos)
if(notifyProcessedVideos){
updateLastVideoData(refreshVideosMinutes);
}
// console.log(GM_info['script']['version']);
function contryCodesArray(){return{"Andorra":"ad","United Arab Emirates":"ae","Afghanistan":"af","Antigua and Barbuda":"ag","Anguilla":"ai","Albania":"al","Armenia":"am","Angola":"ao","Antarctica":"aq","Argentina":"ar","American Samoa":"as","Austria":"at","Australia":"au","Aruba":"aw","Åland Islands":"ax","Azerbaijan":"az","Bosnia and Herzegovina":"ba","Barbados":"bb","Bangladesh":"bd","Belgium":"be","Burkina Faso":"bf","Bulgaria":"bg","Bahrain":"bh","Burundi":"bi","Benin":"bj","Saint Barthélemy":"bl","Bermuda":"bm","Brunei":"bn","Bolivia":"bo","Caribbean Netherlands":"bq","Brazil":"br","Bahamas":"bs","Bhutan":"bt","Bouvet Island":"bv","Botswana":"bw","Belarus":"by","Belize":"bz","Canada":"ca","Cocos (Keeling) Islands":"cc","DR Congo":"cd","Central African Republic":"cf","Republic of the Congo":"cg","Switzerland":"ch","Côte d'Ivoire (Ivory Coast)":"ci","Cook Islands":"ck","Chile":"cl","Cameroon":"cm","China":"cn","Colombia":"co","Costa Rica":"cr","Cuba":"cu","Cape Verde":"cv","Curaçao":"cw","Christmas Island":"cx","Cyprus":"cy","Czechia":"cz","Germany":"de","Djibouti":"dj","Denmark":"dk","Dominica":"dm","Dominican Republic":"do","Algeria":"dz","Ecuador":"ec","Estonia":"ee","Egypt":"eg","Western Sahara":"eh","Eritrea":"er","Spain":"es","Ethiopia":"et","European Union":"eu","Finland":"fi","Fiji":"fj","Falkland Islands":"fk","Micronesia":"fm","Faroe Islands":"fo","France":"fr","Gabon":"ga","United Kingdom":"gb","England":"gb-eng","Northern Ireland":"gb-nir","Scotland":"gb-sct","Wales":"gb-wls","Grenada":"gd","Georgia":"ge","French Guiana":"gf","Guernsey":"gg","Ghana":"gh","Gibraltar":"gi","Greenland":"gl","Gambia":"gm","Guinea":"gn","Guadeloupe":"gp","Equatorial Guinea":"gq","Greece":"gr","South Georgia":"gs","Guatemala":"gt","Guam":"gu","Guinea-Bissau":"gw","Guyana":"gy","Hong Kong":"hk","Heard Island and McDonald Islands":"hm","Honduras":"hn","Croatia":"hr","Haiti":"ht","Hungary":"hu","Indonesia":"id","Ireland":"ie","Israel":"il","Isle of Man":"im","India":"in","British Indian Ocean Territory":"io","Iraq":"iq","Iran":"ir","Iceland":"is","Italy":"it","Jersey":"je","Jamaica":"jm","Jordan":"jo","Japan":"jp","Kenya":"ke","Kyrgyzstan":"kg","Cambodia":"kh","Kiribati":"ki","Comoros":"km","Saint Kitts and Nevis":"kn","North Korea":"kp","South Korea":"kr","Kuwait":"kw","Cayman Islands":"ky","Kazakhstan":"kz","Laos":"la","Lebanon":"lb","Saint Lucia":"lc","Liechtenstein":"li","Sri Lanka":"lk","Liberia":"lr","Lesotho":"ls","Lithuania":"lt","Luxembourg":"lu","Latvia":"lv","Libya":"ly","Morocco":"ma","Monaco":"mc","Moldova":"md","Montenegro":"me","Saint Martin":"mf","Madagascar":"mg","Marshall Islands":"mh","North Macedonia":"mk","Mali":"ml","Myanmar":"mm","Mongolia":"mn","Macau":"mo","Northern Mariana Islands":"mp","Martinique":"mq","Mauritania":"mr","Montserrat":"ms","Malta":"mt","Mauritius":"mu","Maldives":"mv","Malawi":"mw","Mexico":"mx","Malaysia":"my","Mozambique":"mz","Namibia":"na","New Caledonia":"nc","Niger":"ne","Norfolk Island":"nf","Nigeria":"ng","Nicaragua":"ni","Netherlands":"nl","Norway":"no","Nepal":"np","Nauru":"nr","Niue":"nu","New Zealand":"nz","Oman":"om","Panama":"pa","Peru":"pe","French Polynesia":"pf","Papua New Guinea":"pg","Philippines":"ph","Pakistan":"pk","Poland":"pl","Saint Pierre and Miquelon":"pm","Pitcairn Islands":"pn","Puerto Rico":"pr","Palestine":"ps","Portugal":"pt","Palau":"pw","Paraguay":"py","Qatar":"qa","Réunion":"re","Romania":"ro","Serbia":"rs","Russia":"ru","Rwanda":"rw","Saudi Arabia":"sa","Solomon Islands":"sb","Seychelles":"sc","Sudan":"sd","Sweden":"se","Singapore":"sg","Saint Helena, Ascension and Tristan da Cunha":"sh","Slovenia":"si","Svalbard and Jan Mayen":"sj","Slovakia":"sk","Sierra Leone":"sl","San Marino":"sm","Senegal":"sn","Somalia":"so","Suriname":"sr","South Sudan":"ss","São Tomé and Príncipe":"st","El Salvador":"sv","Sint Maarten":"sx","Syria":"sy","Eswatini (Swaziland)":"sz","Turks and Caicos Islands":"tc","Chad":"td","French Southern and Antarctic Lands":"tf","Togo":"tg","Thailand":"th","Tajikistan":"tj","Tokelau":"tk","Timor-Leste":"tl","Turkmenistan":"tm","Tunisia":"tn","Tonga":"to","Turkey":"tr","Trinidad and Tobago":"tt","Tuvalu":"tv","Taiwan":"tw","Tanzania":"tz","Ukraine":"ua","Uganda":"ug","United States Minor Outlying Islands":"um","United Nations":"un","United States":"us","Uruguay":"uy","Uzbekistan":"uz","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"}}
// retrieveValueFromStorage
// saveValue
function updateAlert(){
let lastCheck = retrieveValueFromStorage('lastVersionCheckDate');
// console.log("lastCheck:",lastCheck)
let lastVersionCheckDate;
if (!lastCheck) {
lastVersionCheckDate = currentDate;
} else {
lastVersionCheckDate = new Date(lastCheck);
}
let dateDifference = currentDate - lastVersionCheckDate;
// console.log("dateDifference:",dateDifference)
if(dateDifference > 3 * 24 * 60 * 60 * 1000){
saveValue('lastVersionCheckDate', currentDate.toString());
fetchAndParseHTML(metaPage, (htmlDoc) => {
const metaContent = htmlDoc.body.textContent;
const metaVersionMatch = metaContent.match(/@version\s+([^\s]+)/);
if (metaVersionMatch) {
const latestVersion = metaVersionMatch[1];
console.log("Current version:",currentVersion,"Latest version:",latestVersion)
if (latestVersion !== currentVersion){
if (confirm('A new version of the CUM script is available.\nPlease allow automatic updates or update it manually.\nOpen in new tab?')){
GM_openInTab("https://sleazyfork.org/en/scripts/491272-camwhores-tv-utilities-mod");
}else{
toggleChange(updateRemindersOptionName, false);
console.log("Didn't confirm")
}
}
}
});
}
}
if(updateReminders){
updateAlert();
}
})();