Greasy Fork is available in English.
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();
}
})();