// ==UserScript== // @name Platesmania Lookup Toolbox // @version 1.12.0 // @description Shows lookup buttons on Platesmania upload pages. // @match https://platesmania.com/*/add* // @grant GM_setValue // @grant GM_getValue // @grant GM_xmlhttpRequest // @connect opendata.rdw.nl // @connect motonet.fi // @license MIT // @namespace https://greasyfork.org/users/976031 // @downloadURL none // ==/UserScript== (function () { 'use strict'; // --- Settings & Storage --- // View size can be Large or Compact (formerly "Small"). // We support a default and per-country overrides, plus per-country hidden sites. const SIZE_DEFAULT_KEY = 'lookup_button_size_default'; const SIZE_BY_COUNTRY_KEY = 'lookup_button_size_by_country'; // JSON object { code: 'Large'|'Compact' } const HIDDEN_SITES_BY_COUNTRY_KEY = 'lookup_hidden_sites_by_country'; // JSON object { code: [siteName, ...] } const DISABLE_GOOGLE_IMAGES_KEY = 'lookup_disable_google_images'; const DISABLE_AUTOGESPOT_KEY = 'lookup_disable_autogespot'; function getCurrentCountryCode() { return (supportedCodes || []).find(isPage) || ''; } function readJsonFromStorage(key, fallback) { try { if (typeof GM_getValue === 'function') { const raw = GM_getValue(key, ''); if (!raw) return fallback; try { return JSON.parse(raw); } catch {} } else if (typeof localStorage !== 'undefined') { const raw = localStorage.getItem(key); if (!raw) return fallback; try { return JSON.parse(raw); } catch {} } } catch {} return fallback; } function writeJsonToStorage(key, obj) { const raw = JSON.stringify(obj || {}); try { if (typeof GM_setValue === 'function') GM_setValue(key, raw); else if (typeof localStorage !== 'undefined') localStorage.setItem(key, raw); } catch {} } function readStringFromStorage(key, fallback) { try { if (typeof GM_getValue === 'function') return GM_getValue(key, fallback); if (typeof localStorage !== 'undefined') return localStorage.getItem(key) || fallback; } catch {} return fallback; } function writeStringToStorage(key, val) { try { if (typeof GM_setValue === 'function') GM_setValue(key, val); else if (typeof localStorage !== 'undefined') localStorage.setItem(key, val); } catch {} } function migrateLegacySizeDefault() { // Migrate from old global key 'lookup_button_size_mode' if present const LEGACY_KEY = 'lookup_button_size_mode'; const legacy = readStringFromStorage(LEGACY_KEY, ''); if (legacy) { const normalized = legacy === 'Small' ? 'Compact' : legacy; writeStringToStorage(SIZE_DEFAULT_KEY, normalized); try { if (typeof GM_setValue === 'function') GM_setValue(LEGACY_KEY, ''); else if (localStorage) localStorage.removeItem(LEGACY_KEY); } catch {} } } function getDefaultSizeMode() { migrateLegacySizeDefault(); const val = readStringFromStorage(SIZE_DEFAULT_KEY, 'Large'); return val === 'Small' ? 'Compact' : (val || 'Large'); } function setDefaultSizeMode(mode) { const normalized = mode === 'Small' ? 'Compact' : mode; writeStringToStorage(SIZE_DEFAULT_KEY, normalized); } function getSizeModeForCountry(code) { const byCountry = readJsonFromStorage(SIZE_BY_COUNTRY_KEY, {}); const val = byCountry[code]; if (val) return val === 'Small' ? 'Compact' : val; return getDefaultSizeMode(); } function setSizeModeForCountry(code, mode) { const normalized = mode === 'Small' ? 'Compact' : mode; const byCountry = readJsonFromStorage(SIZE_BY_COUNTRY_KEY, {}); byCountry[code] = normalized; writeJsonToStorage(SIZE_BY_COUNTRY_KEY, byCountry); } function clearAllCountrySizeOverrides() { writeJsonToStorage(SIZE_BY_COUNTRY_KEY, {}); } function isCompactMode() { const code = getCurrentCountryCode(); const mode = code ? getSizeModeForCountry(code) : getDefaultSizeMode(); return mode === 'Compact'; } function getHiddenSitesForCountry(code) { const data = readJsonFromStorage(HIDDEN_SITES_BY_COUNTRY_KEY, {}); const arr = Array.isArray(data[code]) ? data[code] : []; return new Set(arr); } function setHiddenSitesForCountry(code, hiddenArray) { const data = readJsonFromStorage(HIDDEN_SITES_BY_COUNTRY_KEY, {}); data[code] = Array.from(new Set(hiddenArray || [])); writeJsonToStorage(HIDDEN_SITES_BY_COUNTRY_KEY, data); } function isSiteEnabledForCountry(code, siteName) { const hidden = getHiddenSitesForCountry(code); return !hidden.has(siteName); } function isGoogleImagesGloballyEnabled() { const v = readStringFromStorage(DISABLE_GOOGLE_IMAGES_KEY, '0'); return String(v) !== '1'; } function setGoogleImagesGloballyEnabled(enabled) { writeStringToStorage(DISABLE_GOOGLE_IMAGES_KEY, enabled ? '0' : '1'); } function isAutogespotGloballyEnabled() { const v = readStringFromStorage(DISABLE_AUTOGESPOT_KEY, '0'); return String(v) !== '1'; } function setAutogespotGloballyEnabled(enabled) { writeStringToStorage(DISABLE_AUTOGESPOT_KEY, enabled ? '0' : '1'); } // Favicon cache so we don't keep refetching once resolved const faviconCache = {}; function getFaviconConfigForUrl(urlStr) { try { const u = new URL(urlStr); const key = u.hostname; const cached = faviconCache[key]; if (cached) { return { key, candidates: [cached] }; } const s2 = `https://www.google.com/s2/favicons?sz=64&domain=${u.hostname}`; const ico = `${u.origin}/favicon.ico`; return { key, candidates: [ico, s2] }; } catch { return { key: '', candidates: [] }; } } const lookupSites = { nl: [ { name: 'Finnik', base: 'https://finnik.nl/kenteken/' }, { name: 'Autoweek', base: 'https://www.autoweek.nl/kentekencheck/' }, { name: 'voertuig.net', base: 'https://voertuig.net/kenteken/' }, { name: 'Centraal Beheer', base: 'https://centraalbeheer.finnik.nl/kenteken/' }, { name: 'Kentekencheck.info', base: 'https://www.kentekencheck.info/kenteken/' }, { name: 'Kentekencheck.nu', base: 'https://www.kentekencheck.nu/kenteken/' }, { name: 'Qenteken', base: 'https://www.qenteken.nl/kentekencheck/' }, { name: 'RDW (Site)', base: 'https://www.rdwdata.nl/kenteken/' }, ], se: [ { name: 'car.info', base: 'https://www.car.info/?s=' }, { name: 'biluppgifter.se', base: 'https://biluppgifter.se/fordon/' }, { name: 'transportstyrelsen', base: 'https://fordon-fu-regnr.transportstyrelsen.se/?ts-regnr-sok=' }, ], ua: [ { name: 'carplates.app', base: 'https://ua.carplates.app/en/number/' }, { name: 'baza-gai.com.ua', base: 'https://baza-gai.com.ua/nomer/' }, { name: 'auto-inform.com.ua', base: 'https://auto-inform.com.ua/search/' }, ], uk: [ { name: 'checkcardetails', base: 'https://www.checkcardetails.co.uk/cardetails/' }, { name: 'totalcarcheck', base: 'https://totalcarcheck.co.uk/FreeCheck?regno=' }, { name: 'checkhistory', base: 'https://checkhistory.uk/vehicle/' }, { name: 'carcheck', base: 'https://www.carcheck.co.uk/sendnudes/' }, { name: 'carhistorycheck', base: 'https://carhistorycheck.co.uk/confirm-vehicle/?vrm=' }, ], dk: [ { name: 'digitalservicebog.dk', base: 'https://app.digitalservicebog.dk/search?country=dk&Registration=' }, { name: 'esyn.dk', base: 'https://findsynsrapport.esyn.dk/result?registration=' }, ], no: [{ name: 'vegvesen.no', base: 'https://www.vegvesen.no/en/vehicles/buy-and-sell/vehicle-information/check-vehicle-information/?registreringsnummer=' }, { name: 'regnr.info', base: 'https://regnr.info/' } ], fr: [ { name: 'immatriculation-auto.info', base: 'https://immatriculation-auto.info/vehicle/' }, { name: 'carter-cash.com', base: 'https://www.carter-cash.com/pieces-auto/?plate=', needsHyphen: true }, ], es: [ { name: 'carter-cash.es', base: 'https://www.carter-cash.es/piezas-auto/?plate=' }, ], fi: [ { name: 'Biltema', base: 'https://www.biltema.fi/sv-fi/rekosok-bil/' }, { name: 'Motonet (in new tab)', base: 'https://www.motonet.fi/api/vehicleInfo/registrationNumber/FI?locale=fi®istrationNumber=' }, ], cz: [{ name: 'uniqa.cz', base: 'https://www.uniqa.cz/online/pojisteni-vozidla/#ecvId=' }], sk: [{ name: 'overenie.digital', base: 'https://overenie.digital/over/sk/ecv/' }, { name: 'stkonline', base: 'https://www.stkonline.sk/spz/' } ], ie: [{ name: 'cartell.ie', base: 'https://www.cartell.ie/ssl/servlet/beginStarLookup?registration=' }, { name: 'motorcheck.ie', base: 'https://www.motorcheck.ie/free-car-check/?vrm=' } ], is: [{ name: 'island.is', base: 'https://island.is/uppfletting-i-oekutaekjaskra?vq=' }], }; const url = window.location.href; const isPage = (code) => url.includes(`platesmania.com/${code}/add`); const supportedCodes = ['nl','ua','no','dk','fr','uk','fi','pl','lt','cz','se','es', 'sk', 'us', 'ie', 'is']; // Platesmania US: mapping of