您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Add a Google Lens button on Platesmania and auto-fill the image URL into the Google page
// ==UserScript== // @name Platesmania → Google Lens // @namespace http://tampermonkey.net/ // @version 1.1.2 // @description Add a Google Lens button on Platesmania and auto-fill the image URL into the Google page // @author You // @match https://platesmania.com/*/add* // @match https://www.google.com/* // @match https://www.google.*/* // @grant GM.setValue // @grant GM.getValue // @license MIT // ==/UserScript== (function () { 'use strict'; // ---------- Utils ---------- const q = (sel, root = document) => root.querySelector(sel); // Detect our special Google page via query params (so we don't run on every Google page). function isOurGooglePage() { try { const url = new URL(window.location.href); return url.hostname.startsWith('www.google') && url.searchParams.has('olud') && url.searchParams.get('src') === 'pm'; } catch { return false; } } // ---------- Platesmania integration ---------- function handlePlatesmania() { // Create the button const button = document.createElement('button'); button.textContent = 'Google Lens'; button.style.cssText = 'margin-bottom:10px;width:100%;height:23px;display:flex;align-items:center;justify-content:center;background-color:#3498db;color:#fff;border:0;cursor:pointer;border-radius:4px;font-weight:400;'; const targetContainer = q('#zoomimgid'); if (targetContainer) { const existingContainer = targetContainer.previousElementSibling; if (existingContainer && existingContainer.style.width === '260px') { existingContainer.appendChild(button); } else { const container = document.createElement('div'); container.style.cssText = 'margin-left:0;width:260px;display:inline-block;'; container.appendChild(button); targetContainer.parentNode.insertBefore(container, targetContainer); } } // Save the image URL once and whenever it changes (no tight polling). const img = q('#zoomimg'); if (img) { const save = () => GM.setValue('platesmaniaImage', img.src || ''); save(); new MutationObserver(save).observe(img, { attributes: true, attributeFilter: ['src'], }); } // Open Google page with marker params so our other handler knows to run. button.addEventListener('click', () => { window.open('https://www.google.com/?olud&src=pm', '_blank'); }); } // ---------- Google page automation (locale-agnostic) ---------- function handleGoogleImages() { let searchAttempted = false; let tries = 0; const MAX_TRIES = 120; // ~18s at 150ms async function attemptSearch() { if (searchAttempted) return; try { const imageData = await GM.getValue('platesmaniaImage', ''); if (!imageData) return; // Prefer stable attributes, NOT localized placeholders or random classes. // Observed stable targets: // - URL input: input[jsname="W7hAGe"] // - Search button: div[role="button"][jsname="ZtOxCb"] let inputField = q('input[jsname="W7hAGe"]') || q('input.cB9M7') || // fallback observed class q('input[type="text"]'); let searchButton = q('div[role="button"][jsname="ZtOxCb"]') || q('button[type="submit"]') || q('button,div[role="button"]'); if (!inputField || !searchButton) return; // Fill input robustly inputField.focus(); inputField.value = imageData; inputField.dispatchEvent(new Event('input', { bubbles: true })); inputField.dispatchEvent(new Event('change', { bubbles: true })); // Click the button searchButton.click(); // Fallback: press Enter if click didn’t trigger setTimeout(() => { if (!searchAttempted) { const ev = new KeyboardEvent('keydown', { bubbles: true, cancelable: true, key: 'Enter', code: 'Enter', which: 13, keyCode: 13, }); inputField.dispatchEvent(ev); } }, 400); searchAttempted = true; } catch (error) { console.error('Error handling Google Images:', error); } } // Gentle polling with backoff cap const searchInterval = setInterval(() => { if (searchAttempted || tries++ > MAX_TRIES) { clearInterval(searchInterval); } else { attemptSearch(); } }, 150); // Also try once on DOMContentLoaded (in case elements are already present) if (document.readyState !== 'loading') { attemptSearch(); } else { document.addEventListener('DOMContentLoaded', attemptSearch, { once: true }); } } // ---------- Router ---------- const href = window.location.href; if (/https?:\/\/(?:www\.)?platesmania\.com\//.test(href)) { handlePlatesmania(); } else if (isOurGooglePage()) { handleGoogleImages(); } })();