Show search buttons when text is highlighted on specific websites
// ==UserScript==
// @name Highlight Text Search Buttons - Quick Cam Model Lookup / Find
// @namespace http://tampermonkey.net/
// @version 1.2
// @description Show search buttons when text is highlighted on specific websites
// @match *://onlyfans.com/*
// @match *://camwhores.tv/*
// @match https://www.camwhores.tv/*
// @match https://www.showcamrips.com/*
// @match *://livecamrips.to/*
// @match *://simpcity.cr/*
// @match *://camgirlfinder.net/*
// @match *://nrtool.to/*
// @match *://archivebate.com/*
// @match *://nobodyhome.ws/*
// @match *://camsmut.com/*
// @match *://stripchat.com/*
// @match *://*.bongocams.com/*
// @match *://www.sexycamx.com/*
// @match *://chaturbate.com/*
// @grant GM_openInTab
// @grant unsafeWindow
// @license None
// ==/UserScript==
(function() {
'use strict';
// ============ CONFIGURATION ============
// Default search sites configuration
const defaultSites = [
{ name: 'showcamrips', url: 'https://showcamrips.com/model/en/{username}/' },
{ name: 'livecamrips', url: 'https://www.livecamrips.to/search/{username}/1' },
{ name: 'archivebate', url: 'https://archivebate.com/profile/{username}' },
{ name: 'camsmut', url: 'https://camsmut.com/search?q={username}//' },
{ name: 'camwhores', url: 'https://camwhores.tv/search/{username}/' },
{ name: 'nobodyhome', url: 'https://nobodyhome.ws/search.php?action=do_search&postthread=1&keywords={username}' },
{ name: 'camgirlfinder', url: 'https://camgirlfinder.net/models?model={username}&platform=&gender=' },
{ name: 'nrtool', url: 'https://nrtool.to/nrtool/search?s={username}' },
{ name: 'simpcity', url: 'https://simpcity.cr/search/1/?q={username}' },
{ name: 'bongocams', url: 'https://ru2.bongocams.com/{username}' },
{ name: 'stripchat', url: 'https://stripchat.com/{username}' },
{ name: 'onlyfans', url: 'https://onlyfans.com/{username}' },
{ name: 'sexycamx', url: 'https://www.sexycamx.com/{username}' },
];
// ============ SCRIPT LOGIC ============
let buttonContainer = null;
let selectedText = '';
let useLowercase = false;
// Enhanced function to open URL in new tab (bypasses site restrictions)
function openUrlInNewTab(url) {
// Method 1: Try GM_openInTab if available (most reliable)
if (typeof GM_openInTab !== 'undefined') {
try {
GM_openInTab(url, { active: false, insert: true });
return;
} catch (e) {
console.log('GM_openInTab failed, trying alternatives');
}
}
// Method 2: Create a temporary anchor element with download attribute trick
try {
const a = document.createElement('a');
a.href = url;
a.target = '_blank';
a.rel = 'noopener noreferrer';
// This helps bypass some restrictions
a.style.display = 'none';
document.body.appendChild(a);
// Dispatch a real click event
const evt = new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window
});
a.dispatchEvent(evt);
// Clean up
setTimeout(() => document.body.removeChild(a), 100);
return;
} catch (e) {
console.log('Anchor method failed, trying window.open');
}
// Method 3: Standard window.open with enhanced parameters
try {
const newWindow = window.open(url, '_blank', 'noopener,noreferrer');
if (newWindow) {
newWindow.opener = null;
}
} catch (e) {
// Method 4: Last resort - use location.href in a timeout
console.log('All methods failed, using location fallback');
setTimeout(() => {
window.location.href = url;
}, 100);
}
}
// Create button container
function createButtonContainer() {
const container = document.createElement('div');
container.id = 'highlight-search-container';
container.style.cssText = `
position: fixed;
bottom: 20px;
right: 20px;
display: none;
flex-direction: column;
gap: 6px;
z-index: 999999;
padding: 10px;
background: rgba(255, 255, 255, 0.98);
border-radius: 10px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
backdrop-filter: blur(10px);
border: 1px solid rgba(0, 0, 0, 0.1);
max-width: 180px;
max-height: 80vh;
overflow-y: auto;
`;
// Add title
const title = document.createElement('div');
title.textContent = 'Search with:';
title.style.cssText = `
font-size: 11px;
font-weight: 600;
color: #666;
margin-bottom: 2px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
`;
container.appendChild(title);
// Add lowercase checkbox
const checkboxContainer = document.createElement('label');
checkboxContainer.style.cssText = `
display: flex;
align-items: center;
gap: 6px;
font-size: 11px;
color: #666;
margin-bottom: 4px;
cursor: pointer;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
`;
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.checked = useLowercase;
checkbox.style.cssText = `
cursor: pointer;
width: 14px;
height: 14px;
`;
checkbox.addEventListener('change', (e) => {
useLowercase = e.target.checked;
});
const checkboxLabel = document.createElement('span');
checkboxLabel.textContent = 'Lowercase';
checkboxContainer.appendChild(checkbox);
checkboxContainer.appendChild(checkboxLabel);
container.appendChild(checkboxContainer);
// Create buttons
defaultSites.forEach(site => {
const button = document.createElement('button');
button.textContent = site.name;
button.style.cssText = `
padding: 6px 10px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 12px;
font-weight: 500;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
transition: all 0.2s ease;
white-space: nowrap;
text-align: center;
`;
button.addEventListener('mouseenter', () => {
button.style.transform = 'translateY(-1px)';
button.style.boxShadow = '0 2px 8px rgba(0, 0, 0, 0.2)';
});
button.addEventListener('mouseleave', () => {
button.style.transform = 'translateY(0)';
button.style.boxShadow = 'none';
});
button.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
const username = useLowercase ? selectedText.toLowerCase() : selectedText;
const finalUrl = site.url.replace('{username}', encodeURIComponent(username));
openUrlInNewTab(finalUrl);
});
container.appendChild(button);
});
// Add close button
const closeBtn = document.createElement('button');
closeBtn.textContent = '✕';
closeBtn.style.cssText = `
position: absolute;
top: 6px;
right: 6px;
width: 20px;
height: 20px;
border: none;
background: rgba(0, 0, 0, 0.1);
border-radius: 50%;
cursor: pointer;
font-size: 12px;
color: #666;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
`;
closeBtn.addEventListener('mouseenter', () => {
closeBtn.style.background = 'rgba(0, 0, 0, 0.2)';
});
closeBtn.addEventListener('mouseleave', () => {
closeBtn.style.background = 'rgba(0, 0, 0, 0.1)';
});
closeBtn.addEventListener('click', () => {
container.style.display = 'none';
});
container.appendChild(closeBtn);
document.body.appendChild(container);
return container;
}
// Handle text selection
function handleTextSelection() {
const selection = window.getSelection();
const text = selection.toString().trim();
if (text.length > 0) {
selectedText = text;
if (!buttonContainer) {
buttonContainer = createButtonContainer();
}
buttonContainer.style.display = 'flex';
} else {
if (buttonContainer) {
buttonContainer.style.display = 'none';
}
}
}
// Event listeners
document.addEventListener('mouseup', handleTextSelection);
document.addEventListener('keyup', handleTextSelection);
document.addEventListener('selectionchange', handleTextSelection);
// Hide buttons when clicking outside
document.addEventListener('click', (e) => {
if (buttonContainer && !buttonContainer.contains(e.target)) {
const selection = window.getSelection();
if (selection.toString().trim().length === 0) {
buttonContainer.style.display = 'none';
}
}
});
})();