// ==UserScript== // @name 搜索引擎工具栏(改) // @namespace https://github.com/examplecode/useful-user-scripts // @homepageURL https://scriptcat.org/zh-CN/users/157252 // @author examplecode && Aloazny && Gemini // @version 6.5 // @description 二改@examplecode的搜索脚本,感谢@examplecode,添加MD3配色+高斯模糊+编辑/添加搜索引擎功能+搜索栏切换顶部底部+搜索框,保留原本的X浏览器搜索引擎读取,排序等功能。 // @match *://*/* // @icon data:image/png;base64,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 // @license MIT // @run-at document-end // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // @grant GM_EX_getSearchEngines // @grant GM_xmlhttpRequest // @connect suggestion.baidu.com // @connect suggestqueries.google.com // @connect api.bing.com // ==/UserScript== (function() { 'use strict'; const STORAGE_KEY = 'quick_search_bar_final'; const THEME_KEY = 'quick_search_theme_v2'; const LAYOUT_KEY = 'quick_search_layout_v1'; const queryParams = ["q", "s", "p", "wd", "word", "keyword", "text", "query", "key", "result", "searchWord", "search-result" ]; const longSignals = ['search', 'search-result', 'category', 'find', 'query', 'result', 'tags', 'tag']; const strictSignals = ['s', 'k', 'p']; const defaultTheme = { primary: '#6750a4', opacity: 0.7, blur: 18, themeStyle: 'MIUIX' }; const defaultLayout = { pos: 'bottom', offset: 24, autoHide: false, showInput: false, inputStyle: 1, shrinkMode: false, historyLimit: 100, showSuggest: true }; const HISTORY_KEY = 'quick_search_history_v1'; const defaultEngines = [ { name: '必应', host: 'bing.com', url: 'https://www.bing.com/search?q=%s' }, { name: 'Yandex', host: 'yandex', url: 'https://yandex.com/search/touch/?text=%s' }, { name: 'Google', host: 'google', url: 'https://www.google.com/search?q=%s' }, { name: '百度', host: 'baidu.com', url: 'https://www.baidu.com/s?word=%s' }, { name: 'ScriptCat', host: 'scriptcat.org', url: 'https://scriptcat.org/zh-CN/search?keyword=%s' }, { name: '4Khd', host: '/(4khd|xxtt|ssuu|uuss)\\.(com|ink|uk)/', url: 'https://www.4khd.com/search/%s' }, { name: '纳米AI', host: 'n.cn', url: 'https://www.n.cn/search/?q=%s&src=ec_vivo_1001' } ]; const storage = { save: (engines, deletedIds) => { const data = { custom: engines.filter(e => e.isCustom), order: engines.map(e => e.id), hidden: engines.filter(e => !e.visible).map(e => e.id), deleted: deletedIds || [], pathRules: saved.pathRules || {}, cache: engines.map(e => ({ name: e.name, host: e.host, url: e.url, id: e.id, visible: e.visible, isCustom: e.isCustom, pathRule: (saved.pathRules && saved.pathRules[e.host]) || '' })) }; if (typeof GM_setValue !== 'undefined') GM_setValue(STORAGE_KEY, data); else localStorage.setItem(STORAGE_KEY, JSON.stringify(data)); }, load: () => { let data; if (typeof GM_getValue !== 'undefined') data = GM_getValue(STORAGE_KEY); else { try { data = JSON.parse(localStorage.getItem(STORAGE_KEY)); } catch(e) {} } return data || { custom: [], order: [], hidden: [], deleted: [], pathRules: {}, cache: null }; }, themeSave: (val) => { if (typeof GM_setValue !== 'undefined') GM_setValue(THEME_KEY, val); else localStorage.setItem(THEME_KEY, JSON.stringify(val)); applyTheme(); }, themeLoad: () => { let data; if (typeof GM_getValue !== 'undefined') data = GM_getValue(THEME_KEY); else { try { data = JSON.parse(localStorage.getItem(THEME_KEY)); } catch(e) {} } return data || defaultTheme; }, layoutSave: (val) => { if (typeof GM_setValue !== 'undefined') GM_setValue(LAYOUT_KEY, val); else localStorage.setItem(LAYOUT_KEY, JSON.stringify(val)); }, layoutLoad: () => { let data; if (typeof GM_getValue !== 'undefined') data = GM_getValue(LAYOUT_KEY); else { try { data = JSON.parse(localStorage.getItem(LAYOUT_KEY)); } catch(e) {} } return data || defaultLayout; }, getStableId: (name, host) => { let str = (name || '') + '|' + (host || ''); let hash = 0; for (let i = 0; i < str.length; i++) { hash = ((hash << 5) - hash + str.charCodeAt(i)) | 0; } return 'se_' + Math.abs(hash).toString(36); } }; const repairData = () => { let logs = []; let sData = storage.load(); if (!sData || typeof sData !== 'object' || Array.isArray(sData)) { sData = { custom: [], order: [], hidden: [], deleted: [], pathRules: {}, cache: null }; logs.push("基础存储结构异常,已初始化"); } else { if (!Array.isArray(sData.custom)) { sData.custom = []; logs.push("修复 custom 列表"); } if (!Array.isArray(sData.order)) { sData.order = []; logs.push("修复 order 列表"); } if (!Array.isArray(sData.hidden)) { sData.hidden = []; logs.push("修复 hidden 列表"); } if (!Array.isArray(sData.deleted)) { sData.deleted = []; logs.push("修复 deleted 列表"); } if (!sData.pathRules || typeof sData.pathRules !== 'object') { sData.pathRules = {}; logs.push("修复 pathRules 结构"); } } storage.save((sData.cache || []), sData.deleted); let tData = storage.themeLoad(); let tFixed = false; if (!tData || typeof tData !== 'object') { tData = { ...defaultTheme }; tFixed = true; } else { for (let key in defaultTheme) { if (tData[key] === undefined) { tData[key] = defaultTheme[key]; tFixed = true; } } } if (tFixed) { storage.themeSave(tData); logs.push("补全了主题缺失参数"); } let lData = storage.layoutLoad(); let lFixed = false; if (!lData || typeof lData !== 'object' || Array.isArray(lData)) { lData = { ...defaultLayout }; lFixed = true; } else { for (let key in defaultLayout) { if (lData[key] === undefined) { lData[key] = defaultLayout[key]; lFixed = true; } } } if (lFixed) { storage.layoutSave(lData); logs.push("补全了布局缺失参数"); } if (logs.length > 0) { alert("🛠 数据修复完成(已尝试保留原有设置):\n" + logs.join("\n") + "\n\n页面即将刷新。"); location.reload(); } else { alert("✅ 未检测到异常数据。"); } }; if (typeof GM_registerMenuCommand !== 'undefined') { GM_registerMenuCommand("🔍 检查并修复数据", repairData); GM_registerMenuCommand("⚙️ 脚本设置中心", showManager); const createTempHost = () => { const host = document.createElement('div'); host.style.cssText = 'position:absolute;top:-999px;left:-999px;width:0;height:0;overflow:hidden;'; const shadow = host.attachShadow({mode: 'closed'}); document.body.appendChild(host); return { shadow, destroy: () => document.body.removeChild(host) }; }; GM_registerMenuCommand("📤 导出备份 (JSON)", () => { const config = { [STORAGE_KEY]: storage.load(), [THEME_KEY]: storage.themeLoad(), [LAYOUT_KEY]: storage.layoutLoad() }; const { shadow, destroy } = createTempHost(); const blob = new Blob([JSON.stringify(config, null, 2)], { type: 'application/json' }); const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = `search_bar_backup_${Date.now()}.json`; shadow.appendChild(a); a.click(); setTimeout(() => { URL.revokeObjectURL(a.href); destroy(); }, 100); }); GM_registerMenuCommand("📥 导入备份 (覆盖)", () => { const { shadow, destroy } = createTempHost(); const input = document.createElement('input'); input.type = 'file'; input.accept = '.json'; input.onchange = (e) => { const file = e.target.files[0]; if (!file) { destroy(); return; } const reader = new FileReader(); reader.onload = (ev) => { try { const data = JSON.parse(ev.target.result); if (data[THEME_KEY]) storage.themeSave(data[THEME_KEY]); if (data[LAYOUT_KEY]) storage.layoutSave(data[LAYOUT_KEY]); if (data[STORAGE_KEY]) { const d = data[STORAGE_KEY]; d.cache = null; if (typeof GM_setValue !== 'undefined') GM_setValue(STORAGE_KEY, d); else localStorage.setItem(STORAGE_KEY, JSON.stringify(d)); } alert("导入成功,页面即将刷新"); location.reload(); } catch (err) { alert('导入失败:无效的 JSON 格式'); } finally { destroy(); } }; reader.readAsText(file); }; shadow.appendChild(input); input.click(); }); } let theme = storage.themeLoad(); let layout = storage.layoutLoad(); function hexToRgb(hex) { hex = hex.replace('#', ''); if (hex.length === 3) hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; let r = parseInt(hex.substring(0, 2), 16), g = parseInt(hex.substring(2, 4), 16), b = parseInt(hex.substring(4, 6), 16); const brightness = (r * 299 + g * 587 + b * 114) / 1000; const contrastColor = brightness > 150 ? '#000000' : '#ffffff'; return { rgb: `${r}, ${g}, ${b}`, contrast: contrastColor }; } const shadowHost = document.createElement('div'); shadowHost.id = 'qs-shadow-root'; shadowHost.style.cssText = 'position:absolute;z-index:2147483647;'; const shadow = shadowHost.attachShadow({mode: 'open'}); function applyTheme() { const styleId = 'qs-static-styles'; let el = shadow.getElementById(styleId) || document.createElement('style'); el.id = styleId; const themeData = hexToRgb(theme.primary); const isMIUI = theme.themeStyle === 'MIUIX'; const config = isMIUI ? { radius: '100px', btnRadius: '100px', cardRadius: '32px', border: '0.5px solid rgba(255,255,255,0.4)', saturate: '210%', shadow: '0 8px 32px rgba(0,0,0,0.1)' } : { radius: '16px', btnRadius: '12px', cardRadius: '24px', border: '1px solid rgba(0,0,0,0.1)', saturate: '150%', shadow: '0 4px 12px rgba(0,0,0,0.1)' }; el.innerHTML = ` :host { --qs-pri: ${theme.primary}; --qs-pri-rgb: ${themeData.rgb}; --qs-on-pri: ${themeData.contrast}; --qs-bg: rgba(255, 255, 255, ${theme.opacity}); --qs-blur: ${theme.blur}px; --qs-radius: ${config.radius}; --qs-btn-radius: ${config.btnRadius}; --qs-card-radius: ${config.cardRadius}; --qs-border: ${config.border}; --qs-saturate: ${config.saturate}; --qs-shadow: ${config.shadow}; } #qs-manager-overlay { position:fixed;inset:0;background:rgba(0,0,0,0.3);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);z-index:2147483647;display:flex;justify-content:center;align-items:center;font-family:system-ui,-apple-system,BlinkMacSystemFont,sans-serif; } .qs-card { background:rgba(255,255,255,0.85);backdrop-filter:saturate(var(--qs-saturate)) blur(25px);-webkit-backdrop-filter:saturate(var(--qs-saturate)) blur(25px);width:92%;max-width:440px;max-height:80vh;border-radius:var(--qs-card-radius);box-shadow:0 20px 50px rgba(0,0,0,0.15);display:flex;flex-direction:column;overflow:hidden;border:var(--qs-border);color:#1c1b1f;transition: border-radius 0.3s ease;box-sizing:border-box; } .qs-bar { position:fixed; left:50%; transform:translateX(-50%); z-index:2147483646; background:var(--qs-bg); backdrop-filter:saturate(var(--qs-saturate)) blur(var(--qs-blur)); -webkit-backdrop-filter:saturate(var(--qs-saturate)) blur(var(--qs-blur)); display:flex; overflow-x:auto; padding:10px 14px; gap:8px; border-radius:var(--qs-radius); box-shadow:var(--qs-shadow); border:var(--qs-border); max-width:92vw; scrollbar-width:none; align-items:center; transition:transform 0.3s, opacity 0.3s, border-radius 0.3s; scroll-behavior:smooth; box-sizing:border-box; } .qs-bar::-webkit-scrollbar { display:none; } .qs-btn { padding:10px 18px; border-radius:var(--qs-btn-radius); text-decoration:none; font-size:14px; white-space:nowrap; font-weight:600; flex-shrink:0; transition: transform 0.1s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.2s; border:none; cursor:pointer; display:inline-flex; align-items:center; justify-content:center; box-sizing:border-box; } .qs-btn:active { transform: scale(0.92); } .qs-btn-active { background:var(--qs-pri); color:var(--qs-on-pri); } .qs-btn-flat { background:rgba(0,0,0,0.04); color:#1d1b20; } .qs-main-input { border:none; outline:none; font-size:13px; font-weight:500; transition: width 0.3s, background 0.3s; box-sizing:border-box; } .se-item-container { margin-bottom: 10px; border-radius: 20px; border: 1px solid rgba(0,0,0,0.03); background: rgba(255,255,255,0.6); box-sizing:border-box; } .se-item { display: flex; align-items: center; padding: 14px 16px; cursor: pointer; box-sizing:border-box; } .btn-icon { width: 36px; height: 36px; border-radius: 12px; border: none; background: transparent; cursor: pointer; display: flex; align-items: center; justify-content: center; color: #49454f; font-size:18px; box-sizing:border-box; } .toggle-box { width: 44px; height: 24px; background: #e7e0ec; border-radius: 20px; position: relative; transition: 0.3s; margin-right: 12px; flex-shrink:0; } .toggle-box.active { background: var(--qs-pri); } .toggle-circle { width: 18px; height: 18px; background: #fff; border-radius: 50%; position: absolute; top: 3px; left: 3px; transition: 0.3s; } .toggle-box.active .toggle-circle { left: 23px; } .edit-form { max-height: 0; opacity: 0; padding: 0 16px; overflow:hidden; transition: all 0.3s ease; box-sizing:border-box; } .edit-form.open { max-height: 400px; opacity: 1; padding: 10px 16px 20px; } .qs-input-field { width:100% !important; display:block !important; padding:14px; border-radius:12px; border:1px solid rgba(0,0,0,0.1) !important; background:#ffffff !important; color:#000000 !important; outline:none; font-size:14px; box-sizing:border-box !important; } .qs-input-field::placeholder { color: #888 !important; } #m-list::-webkit-scrollbar { display:none; } #mask { position:fixed;inset:0;background:rgba(0,0,0,0.2);backdrop-filter:blur(${theme.blur}px);-webkit-backdrop-filter:blur(${theme.blur}px);z-index:2147483640;display:none; } #box { position:fixed; ${layout.pos === 'top' ? 'top:'+(parseInt(layout.offset)+60)+'px' : 'bottom:'+(parseInt(layout.offset)+60)+'px'}; left:50%; transform:translateX(-50%); width:90vw; max-width:400px; z-index:2147483641; display:none; flex-wrap:wrap; gap:8px; padding:10px; box-sizing:border-box; } .item { padding:8px 16px; background:rgba(255,255,255,0.8); backdrop-filter:blur(10px); border-radius:${isMIUI?'100px':'12px'}; font-size:13px; color:#1d1b20; cursor:pointer; border:1px solid rgba(0,0,0,0.05); transition:0.2s; box-shadow:0 2px 8px rgba(0,0,0,0.05); } .item:hover { background:var(--qs-pri); color:var(--qs-on-pri); } .item.his { border-color:rgba(var(--qs-pri-rgb), 0.3); } `; if (!el.parentNode) shadow.appendChild(el); } const updateSuggestStyle = () => { applyTheme(); if(!shadow.getElementById('mask')){ const m = document.createElement('div'); m.id = 'mask'; const b = document.createElement('div'); b.id = 'box'; shadow.appendChild(m); shadow.appendChild(b); } }; function normalizeUrl(url) { return url ? url.replace(/%keywords%/g, '%s').trim() : ''; } let xEngines = []; if (typeof GM_EX_getSearchEngines === 'function') { try { const list = JSON.parse(GM_EX_getSearchEngines()); if (Array.isArray(list)) { xEngines = list.map(e => ({ name: e.name || '未知', host: e.host || '', url: normalizeUrl(e.url || '') })); } } catch (e) {} } let saved = storage.load(); const suggestApi = { baidu: (s) => `https://suggestion.baidu.com/su?wd=${encodeURIComponent(s)}&p=3&ie=utf-8&oe=utf-8`, google: (s) => `https://suggestqueries.google.com/complete/search?client=chrome&q=${encodeURIComponent(s)}`, bing: (s) => `https://api.bing.com/osjson.aspx?query=${encodeURIComponent(s)}`, fetch: (s, type) => { return new Promise((resolve) => { if (typeof GM_xmlhttpRequest === 'undefined') return resolve([]); GM_xmlhttpRequest({ method: "GET", url: suggestApi[type](s), timeout: 1200, onload: (res) => { try { if (type === 'baidu') { const match = res.responseText.match(/\[.*\]/); resolve(match ? JSON.parse(match[0]) : []); } else if (type === 'google' || type === 'bing') { const data = JSON.parse(res.responseText); resolve(data[1] || []); } } catch (e) { resolve([]); } }, onerror: () => resolve([]), ontimeout: () => resolve([]) }); }); }, fetchAll: async (s, onUpdate) => { let results = { google: [], bing: [], baidu: [] }; const combine = () => { const { google: g, bing: i, baidu: b } = results; if (g.length) return [...new Set([...g.slice(0, 10), ...i.slice(0, 5), ...b.slice(0, 3)])]; if (i.length) return [...new Set([...i.slice(0, 10), ...b.slice(0, 6)])]; return b; }; ['google', 'bing', 'baidu'].forEach(async (type) => { const data = await suggestApi.fetch(s, type); if (data && data.length > 0) { results[type] = data; onUpdate(combine()); } }); } }; const historyManager = { get: () => { try { return JSON.parse(localStorage.getItem(HISTORY_KEY)) || []; } catch(e) { return []; } }, add: (s) => { if (!s || s.startsWith('http')) return; let h = historyManager.get(); h = [s, ...h.filter(i => i !== s)].slice(0, layout.historyLimit || 100); localStorage.setItem(HISTORY_KEY, JSON.stringify(h)); } }; //域名识别 const TLDS_SORTED = "AAA|AARP|ABB|ABBOTT|ABBVIE|ABC|ABLE|ABOGADO|ABUDHABI|AC|ACADEMY|ACCENTURE|ACCOUNTANT|ACCOUNTANTS|ACO|ACTOR|AD|ADS|ADULT|AE|AEG|AERO|AETNA|AF|AFL|AFRICA|AG|AGAKHAN|AGENCY|AI|AIG|AIRBUS|AIRFORCE|AIRTEL|AKDN|AL|ALIBABA|ALIPAY|ALLFINANZ|ALLSTATE|ALLY|ALSACE|ALSTOM|AM|AMAZON|AMERICANEXPRESS|AMERICANFAMILY|AMEX|AMFAM|AMICA|AMSTERDAM|ANALYTICS|ANDROID|ANQUAN|ANZ|AO|AOL|APARTMENTS|APP|APPLE|AQ|AQUARELLE|AR|ARAB|ARAMCO|ARCHI|ARMY|ARPA|ART|ARTE|AS|ASDA|ASIA|ASSOCIATES|AT|ATHLETA|ATTORNEY|AU|AUCTION|AUDI|AUDIBLE|AUDIO|AUSPOST|AUTHOR|AUTO|AUTOS|AW|AWS|AX|AXA|AZ|AZURE|BA|BABY|BAIDU|BANAMEX|BAND|BANK|BAR|BARCELONA|BARCLAYCARD|BARCLAYS|BAREFOOT|BARGAINS|BASEBALL|BASKETBALL|BAUHAUS|BAYERN|BB|BBC|BBT|BBVA|BCG|BCN|BD|BE|BEATS|BEAUTY|BEER|BERLIN|BEST|BESTBUY|BET|BF|BG|BH|BHARTI|BI|BIBLE|BID|BIKE|BING|BINGO|BIO|BIZ|BJ|BLACK|BLACKFRIDAY|BLOCKBUSTER|BLOG|BLOOMBERG|BLUE|BM|BMS|BMW|BN|BNPPARIBAS|BO|BOATS|BOEHRINGER|BOFA|BOM|BOND|BOO|BOOK|BOOKING|BOSCH|BOSTIK|BOSTON|BOT|BOUTIQUE|BOX|BR|BRADESCO|BRIDGESTONE|BROADWAY|BROKER|BROTHER|BRUSSELS|BS|BT|BUILD|BUILDERS|BUSINESS|BUY|BUZZ|BV|BW|BY|BZ|BZH|CA|CAB|CAFE|CAL|CALL|CALVINKLEIN|CAM|CAMERA|CAMP|CANON|CAPETOWN|CAPITAL|CAPITALONE|CAR|CARAVAN|CARDS|CARE|CAREER|CAREERS|CARS|CASA|CASE|CASH|CASINO|CAT|CATERING|CATHOLIC|CBA|CBN|CBRE|CC|CD|CENTER|CEO|CERN|CF|CFA|CFD|CG|CH|CHANEL|CHANNEL|CHARITY|CHASE|CHAT|CHEAP|CHINTAI|CHRISTMAS|CHROME|CHURCH|CI|CIPRIANI|CIRCLE|CISCO|CITADEL|CITI|CITIC|CITY|CK|CL|CLAIMS|CLEANING|CLICK|CLINIC|CLINIQUE|CLOTHING|CLOUD|CLUB|CLUBMED|CM|CN|CO|COACH|CODES|COFFEE|COLLEGE|COLOGNE|COM|COMMBANK|COMMUNITY|COMPANY|COMPARE|COMPUTER|COMSEC|CONDOS|CONSTRUCTION|CONSULTING|CONTACT|CONTRACTORS|COOKING|COOL|COOP|CORSICA|COUNTRY|COUPON|COUPONS|COURSES|CPA|CR|CREDIT|CREDITCARD|CREDITUNION|CRICKET|CROWN|CRS|CRUISE|CRUISES|CU|CUISINELLA|CV|CW|CX|CY|CYMRU|CYOU|CZ|DAD|DANCE|DATA|DATE|DATING|DATSUN|DAY|DCLK|DDS|DE|DEAL|DEALER|DEALS|DEGREE|DELIVERY|DELL|DELOITTE|DELTA|DEMOCRAT|DENTAL|DENTIST|DESI|DESIGN|DEV|DHL|DIAMONDS|DIET|DIGITAL|DIRECT|DIRECTORY|DISCOUNT|DISCOVER|DISH|DIY|DJ|DK|DM|DNP|DO|DOCS|DOCTOR|DOG|DOMAINS|DOT|DOWNLOAD|DRIVE|DTV|DUBAI|DUPONT|DURBAN|DVAG|DVR|DZ|EARTH|EAT|EC|ECO|EDEKA|EDU|EDUCATION|EE|EG|EMAIL|EMERCK|ENERGY|ENGINEER|ENGINEERING|ENTERPRISES|EPSON|EQUIPMENT|ER|ERICSSON|ERNI|ES|ESQ|ESTATE|ET|EU|EUROVISION|EUS|EVENTS|EXCHANGE|EXPERT|EXPOSED|EXPRESS|EXTRASPACE|FAGE|FAIL|FAIRWINDS|FAITH|FAMILY|FAN|FANS|FARM|FARMERS|FASHION|FAST|FEDEX|FEEDBACK|FERRARI|FERRERO|FI|FIDELITY|FIDO|FILM|FINAL|FINANCE|FINANCIAL|FIRE|FIRESTONE|FIRMDALE|FISH|FISHING|FIT|FITNESS|FJ|FK|FLICKR|FLIGHTS|FLIR|FLORIST|FLOWERS|FLY|FM|FO|FOO|FOOD|FOOTBALL|FORD|FOREX|FORSALE|FORUM|FOUNDATION|FOX|FR|FREE|FRESENIUS|FRL|FROGANS|FRONTIER|FTR|FUJITSU|FUN|FUND|FURNITURE|FUTBOL|FYI|GA|GAL|GALLERY|GALLO|GALLUP|GAME|GAMES|GAP|GARDEN|GAY|GB|GBIZ|GD|GDN|GE|GEA|GENT|GENTING|GEORGE|GF|GG|GGEE|GH|GI|GIFT|GIFTS|GIVES|GIVING|GL|GLASS|GLE|GLOBAL|GLOBO|GM|GMAIL|GMBH|GMO|GMX|GN|GODADDY|GOLD|GOLDPOINT|GOLDPOINT|GOLF|GOODYEAR|GOOG|GOOGLE|GOP|GOT|GOV|GP|GQ|GR|GRAINGER|GRAPHICS|GRATIS|GREEN|GRIPE|GROCERY|GROUP|GS|GT|GU|GUCCI|GUGE|GUIDE|GUITARS|GURU|GW|GY|HAIR|HAMBURG|HANGOUT|HAUS|HBO|HDFC|HDFCBANK|HEALTH|HEALTHCARE|HELP|HELSINKI|HERE|HERMES|HIPHOP|HISAMITSU|HITACHI|HIV|HK|HKT|HM|HN|HOCKEY|HOLDINGS|HOLIDAY|HOMEDEPOT|HOMEGOODS|HOMES|HOMESENSE|HONDA|HORSE|HOSPITAL|HOST|HOSTING|HOT|HOTELS|HOTMAIL|HOUSE|HOW|HR|HSBC|HT|HU|HUGHES|HYATT|HYUNDAI|IBM|ICBC|ICE|ICU|ID|IE|IEEE|IFM|IKANO|IL|IM|IMAMAT|IMDB|IMMO|IMMOBILIEN|IN|INC|INDUSTRIES|INFINITI|INFO|ING|INK|INSTITUTE|INSURANCE|INSURE|INT|INTERNATIONAL|INTUIT|INVESTMENTS|IO|IPIRANGA|IQ|IR|IRISH|IS|ISMAILI|IST|ISTANBUL|IT|ITAU|ITV|JAGUAR|JAVA|JCB|JE|JEEP|JETZT|JEWELRY|JIO|JLL|JM|JMP|JNJ|JO|JOBS|JOBURG|JOT|JOY|JP|JPMORGAN|JPRS|JUEGOS|JUNIPER|KAUFEN|KDDI|KE|KERRYHOTELS|KERRYPROPERTIES|KFH|KG|KH|KI|KIA|KIDS|KIM|KINDLE|KITCHEN|KIWI|KM|KN|KOELN|KOMATSU|KOSHER|KP|KPMG|KPN|KR|KRD|KRED|KUOKGROUP|KW|KY|KYOTO|KZ|LA|LACAIXA|LAMBORGHINI|LAMER|LAND|LANDROVER|LANXESS|LASALLE|LAT|LATINO|LATROBE|LAW|LAWYER|LB|LC|LDS|LEASE|LECLERC|LEFRAK|LEGAL|LEGO|LEXUS|LGBT|LI|LIDL|LIFE|LIFEINSURANCE|LIFESTYLE|LIGHTING|LIKE|LILLY|LIMITED|LIMO|LINCOLN|LINK|LIVE|LIVING|LK|LLC|LLP|LOAN|LOANS|LOCKER|LOCUS|LOL|LONDON|LOTTE|LOTTO|LOVE|LPL|LPLFINANCIAL|LR|LS|LT|LTD|LTDA|LU|LUNDBECK|LUXE|LUXURY|LV|LY|MA|MADRID|MAIF|MAISON|MAKEUP|MAN|MANAGEMENT|MANGO|MAP|MARKET|MARKETING|MARKETS|MARRIOTT|MARSHALLS|MATTEL|MBA|MC|MCKINSEY|MD|ME|MED|MEDIA|MEET|MELBOURNE|MEME|MEMORIAL|MEN|MENU|MERCKMSD|MG|MH|MIAMI|MICROSOFT|MIL|MINI|MINT|MIT|MITSUBISHI|MK|ML|MLB|MLS|MM|MMA|MN|MO|MOBI|MOBILE|MODA|MOE|MOI|MOM|MONASH|MONEY|MONSTER|MORMON|MORTGAGE|MOSCOW|MOTO|MOTORCYCLES|MOV|MOVIE|MP|MQ|MR|MS|MSD|MT|MTN|MTR|MU|MUSEUM|MUSIC|MV|MW|MX|MY|MZ|NA|NAB|NAGOYA|NAME|NAVY|NBA|NC|NE|NEC|NET|NETBANK|NETFLIX|NETWORK|NEUSTAR|NEW|NEWS|NEXT|NEXTDIRECT|NEXUS|NF|NFL|NG|NGO|NHK|NI|NICO|NIKE|NIKON|NINJA|NISSAN|NISSAY|NL|NO|NOKIA|NORTON|NOW|NOWRUZ|NOWTV|NP|NR|NRA|NRW|NTT|NU|NYC|NZ|OBI|OBSERVER|OFFICE|OKINAWA|OLAYAN|OLAYANGROUP|OLLO|OM|OMEGA|ONE|ONG|ONL|ONLINE|OOO|OPEN|ORACLE|ORANGE|ORG|ORGANIC|ORIGINS|OSAKA|OTSUKA|OTT|OVH|PA|PAGE|PANASONIC|PARIS|PARS|PARTNERS|PARTS|PARTY|PAY|PCCW|PE|PET|PF|PFIZER|PG|PH|PHARMACY|PHD|PHILIPS|PHONE|PHOTO|PHOTOGRAPHY|PHOTOS|PHYSIO|PICS|PICTET|PICTURES|PID|PIN|PING|PINK|PIONEER|PIZZA|PK|PL|PLACE|PLAY|PLAYSTATION|PLUMBING|PLUS|PM|PN|PNC|POHL|POKER|POLITIE|PORN|POST|PR|PRAXI|PRESS|PRIME|PRO|PROD|PRODUCTIONS|PROF|PROGRESSIVE|PROMO|PROPERTIES|PROPERTY|PROTECTION|PRU|PRUDENTIAL|PS|PT|PUB|PW|PWC|PY|QA|QPON|QUEBEC|QUEST|RACING|RADIO|RE|READ|REALESTATE|REALTOR|REALTY|RECIPES|RED|REDUMBRELLA|REHAB|REISE|REISEN|REIT|RELIANCE|REN|RENT|RENTALS|REPAIR|REPORT|REPUBLICAN|REST|RESTAURANT|REVIEW|REVIEWS|REXROTH|RICH|RICHARDLI|RICOH|RIL|RIO|RIP|RO|ROCKS|RODEO|ROGERS|ROOM|RS|RSVP|RU|RUGBY|RUHR|RUN|RW|RWE|RYUKYU|SA|SAARLAND|SAFE|SAFETY|SAKURA|SALE|SALON|SAMSCLUB|SAMSUNG|SANDVIK|SANDVIKCOROMANT|SANOFI|SAP|SARL|SAS|SAVE|SAXO|SB|SBI|SBS|SC|SCB|SCHAEFFLER|SCHMIDT|SCHOLARSHIPS|SCHOOL|SCHULE|SCHWARZ|SCIENCE|SCOT|SD|SE|SEARCH|SEAT|SECURE|SECURITY|SEEK|SELECT|SENER|SERVICES|SEVEN|SEW|SEX|SEXY|SFR|SG|SH|SHANGRILA|SHARP|SHELL|SHIA|SHIKSHA|SHOES|SHOP|SHOPPING|SHOUJI|SHOW|SI|SILK|SINA|SINGLES|SITE|SJ|SK|SKI|SKIN|SKY|SKYPE|SL|SLING|SM|SMART|SMILE|SN|SNCF|SO|SOCCER|SOCIAL|SOFTBANK|SOFTWARE|SOHU|SOLAR|SOLUTIONS|SONG|SONY|SOY|SPA|SPACE|SPORT|SPOT|SR|SRL|SS|ST|STADA|STAPLES|STAR|STATEBANK|STATEFARM|STC|STCGROUP|STOCKHOLM|STORAGE|STORE|STREAM|STUDIO|STUDY|STYLE|SU|SUCKS|SUPPLIES|SUPPLY|SUPPORT|SURF|SURGERY|SUZUKI|SV|SWATCH|SWISS|SX|SY|SYDNEY|SYSTEMS|SZ|TAB|TAIPEI|TALK|TAOBAO|TARGET|TATAMOTORS|TATAR|TATTOO|TAX|TAXI|TC|TCI|TD|TDK|TEAM|TECH|TECHNOLOGY|TEL|TEMASEK|TENNIS|TEVA|TF|TG|TH|THD|THEATER|THEATRE|TIAA|TICKETS|TIENDA|TIPS|TIRES|TIROL|TJ|TJMAXX|TJX|TK|TKMAXX|TL|TM|TMALL|TN|TO|TODAY|TOKYO|TOOLS|TOP|TORAY|TOSHIBA|TOTAL|TOURS|TOWN|TOYOTA|TOYS|TR|TRADE|TRADE|TRAINING|TRAVEL|TRAVELERS|TRAVELERSINSURANCE|TRUST|TRV|TT|TUBE|TUI|TUNES|TUSHU|TV|TVS|TW|TZ|UA|UBANK|UBS|UG|UK|UNICOM|UNIVERSITY|UNO|UOL|UPS|US|UY|UZ|VA|VACATIONS|VANA|VANGUARD|VC|VE|VEGAS|VENTURES|VERISIGN|VERSICHERUNG|VET|VG|VI|VIAJES|VIDEO|VIG|VIKING|VILLAS|VIN|VIP|VIRGIN|VISA|VISION|VIVA|VIVO|VLAANDEREN|VN|VODKA|VOLVO|VOTE|VOTING|VOTO|VOYAGE|VU|WALES|WALMART|WALTER|WANG|WANGGOU|WATCH|WATCHES|WEATHER|WEATHERCHANNEL|WEBCAM|WEBER|WEBSITE|WED|WEDDING|WEIBO|WEIR|WF|WHOSWHO|WIEN|WIKI|WILLIAMHILL|WIN|WINDOWS|WINE|WINNERS|WME|WOLTERSKLUWER|WOODSIDE|WORK|WORKS|WORLD|WOW|WS|WTC|WTF|XBOX|XEROX|XIHUAN|XIN|XN--11B4C3D|XN--1CK2E1B|XN--1QQW23A|XN--2SCRJ9C|XN--30RR7Y|XN--3BST00M|XN--3DS443G|XN--3E0B707E|XN--3HCRJ9C|XN--3PXU8K|XN--42C2D9A|XN--45BR5CYL|XN--45BRJ9C|XN--45Q11C|XN--4DBRK0CE|XN--4GBRIM|XN--54B7FTA0CC|XN--55QW42G|XN--55QX5D|XN--5SU34J936BGSG|XN--5TZM5G|XN--6FRZ82G|XN--6QQ986B3XL|XN--80ADXHKS|XN--80AO21A|XN--80AQECDR1A|XN--80ASEHDB|XN--80ASWG|XN--8Y0A063A|XN--90A3AC|XN--90AE|XN--90AIS|XN--9DBQ2A|XN--9ET52U|XN--9KRT00A|XN--B4W605FERD|XN--BCK1B9A5DRE4C|XN--C1AVG|XN--C2BR7G|XN--CCK2B3B|XN--CCKWCXETD|XN--CG4BKI|XN--CLCHC0EA0B2G2A9GCD|XN--CZR694B|XN--CZRS0T|XN--CZRU2D|XN--D1ACJ3B|XN--D1ALF|XN--E1A4C|XN--ECKVDTC9D|XN--EFVY88H|XN--FCT429K|XN--FHBEI|XN--FIQ228C5HS|XN--FIQ64B|XN--FIQS8S|XN--FIQZ9S|XN--FJQ720A|XN--FLW351E|XN--FPCRJ9C3D|XN--FZC2C9E2C|XN--FZYS8D69UVGM|XN--G2XX48C|XN--GCKR3F0F|XN--GECRJ9C|XN--GK3AT1E|XN--H2BREG3EVE|XN--H2BRJ9C|XN--H2BRJ9C8C|XN--HXT814E|XN--I1B6B1A6A2E|XN--IMR513N|XN--IO0A7I|XN--J1AEF|XN--J1AMH|XN--J6W193G|XN--JLQ480N2RG|XN--JVR189M|XN--KCRX77D1X4A|XN--KPRW13D|XN--KPRY57D|XN--KPUT3I|XN--L1ACC|XN--LGBBAT1AD8J|XN--MGB9AWBF|XN--MGBA3A3EJT|XN--MGBA3A4F16A|XN--MGBA7C0BBN0A|XN--MGBAAM7A8H|XN--MGBAB2BD|XN--MGBAH1A3HJKRD|XN--MGBAI9AZGQP6J|XN--MGBAYH7GPA|XN--MGBBH1A|XN--MGBBH1A71E|XN--MGBC0A9AZCG|XN--MGBCA7DZDO|XN--MGBCPQ6GPA1A|XN--MGBERP4A5D4AR|XN--MGBGU82A|XN--MGBI4ECEXP|XN--MGBPL2FH|XN--MGBT3DHD|XN--MGBTX2B|XN--MGBX4CD0AB|XN--MIX891F|XN--MK1BU44C|XN--MXTQ1M|XN--NGBC5AZD|XN--NGBE9E0A|XN--NGBRX|XN--NODE|XN--NQV7F|XN--NQV7FS00EMA|XN--NYQY26A|XN--O3CW4H|XN--OGBPF8FL|XN--OTU796D|XN--P1ACF|XN--P1AI|XN--PGBS0DH|XN--PSSY2U|XN--Q7CE6A|XN--Q9JYB4C|XN--QCKA1PMC|XN--QXA6A|XN--QXAM|XN--RHQV96G|XN--ROVU88B|XN--RVC1E0AM3E|XN--S9BRJ9C|XN--SES554G|XN--T60B56A|XN--TCKWE|XN--TIQ49XQYJ|XN--UNUP4Y|XN--VERMGENSBERATER-CTB|XN--VERMGENSBERATUNG-PWB|XN--VHQUV|XN--VUQ861B|XN--W4R85EL8FHU5DNRA|XN--W4RS40L|XN--WGBH1C|XN--WGBL6A|XN--XHQ521B|XN--XKC2AL3HYE2A|XN--XKC2DL3A5EE0H|XN--Y9A3AQ|XN--YFRO4I67O|XN--YGBI2AMMX|XN--ZFR164B|XXX|XYZ|YACHTS|YAHOO|YAMAXUN|YANDEX|YE|YODOBASHI|YOGA|YOKOHAMA|YOU|YOUTUBE|YT|YUN|ZA|ZAPPOS|ZARA|ZERO|ZIP|ZM|ZONE|ZUERICH|ZW".split('|').sort((a, b) => b.length - a.length).join('|'); const FILE_EXTS_REG = /\.(?:zip|7z|rar|tar|gz|bz2|xz|7zip|iso|apk|exe|doc|docx|xls|xlsx|ppt|pptx|pdf|epub|mobi|azw3|chm|txt|md|jpg|jpeg|png|gif|webp|bmp|svg|psd|ai|mp4|mpg|mkv|avi|mov|wmv|flv|webm|mp3|ogg|flac|wav|js|css|prop|url|mht|html|php|py|sh|lua|json|xml|yaml|sql|ps|ts|m4a|rmvb|torrent|cue|ass|srt|ttf|otf|woff)$/i; const PROTOCOL_PREFIX_REG = /^(https?:\/\/|ftp:\/\/|www\.)/i; const TLD_MATCH_REG = new RegExp(`^(${TLDS_SORTED})$`, 'i'); function checkUrl(s) { const str = s.trim(); if (/\s/.test(str)) return null; const protocolMatch = str.match(PROTOCOL_PREFIX_REG); if (!protocolMatch && !str.includes('.')) return null; const urlPath = str.split(/[?#]/)[0]; if (FILE_EXTS_REG.test(urlPath) && !protocolMatch) return null; const hasProtocol = /^(https?:\/\/|ftp:\/\/)/i.test(str); const domain = str.replace(PROTOCOL_PREFIX_REG, '').split(/[/?#]/)[0].toLowerCase(); if (!/^[a-z0-9.-]+$/.test(domain)) return null; const parts = domain.split('.'); const tld = parts[parts.length - 1]; if (TLD_MATCH_REG.test(tld) && parts.length > 1 && parts[0] !== '') return hasProtocol ? str : (str.toLowerCase().startsWith('www.') ? 'https://' + str : 'https://' + str); return hasProtocol ? str : null; } function initEngines() { if (!saved.pathRules) saved.pathRules = {}; const currentXCount = (typeof xEngines !== 'undefined') ? xEngines.length : 0; if (saved.cache && saved.cache.length > 0 && saved._lastXCount === currentXCount) return saved.cache; let pool = []; (saved.custom || []).forEach(e => pool.push({...e, isCustom: true})); defaultEngines.forEach(e => pool.push({...e, isCustom: false})); if (typeof xEngines !== 'undefined') xEngines.forEach(e => pool.push({...e, isCustom: false})); let map = new Map(); const seenUrls = new Set(), seenRegs = new Set(); pool.forEach(e => { const urlKey = (e.url || '').toLowerCase(), host = (e.host || '').trim(), isRegExp = host.startsWith('/') && host.endsWith('/'); let shouldAdd = false; if (isRegExp) { if (!seenRegs.has(host)) { seenRegs.add(host); shouldAdd = true; } } else if (urlKey && !seenUrls.has(urlKey)) { seenUrls.add(urlKey); shouldAdd = true; } if (shouldAdd) { let id = e.id || storage.getStableId(e.name, e.host), finalId = id, suffix = 1; while (map.has(finalId)) finalId = id + '_' + (suffix++); map.set(finalId, { ...e, id: finalId, visible: !(saved.hidden || []).includes(finalId) }); } }); let list = Array.from(map.values()).filter(e => !(saved.deleted || []).includes(e.id)); if (saved.order && saved.order.length > 0) { const orderMap = new Map(saved.order.map((id, i) => [id, i])); list.sort((a, b) => (orderMap.get(a.id) ?? 999) - (orderMap.get(b.id) ?? 999)); } saved._lastXCount = currentXCount; if (list.length > 0) storage.save(list, saved.deleted); return list; } let allEngines = initEngines().map(e => { const h = (e.host || '').trim(); if (h.startsWith('/') && h.endsWith('/')) { try { const p = h.slice(1, -1); e._matchFn = s => new RegExp(p, 'i').test(s); } catch(err) { e._matchFn = s => s.toLowerCase().includes(h.toLowerCase()); } } else { e._matchFn = s => s.toLowerCase().includes(h.toLowerCase()); } return e; }); function showManager() { if (shadow.getElementById('qs-manager-overlay')) return; const overlay = document.createElement('div'); overlay.id = 'qs-manager-overlay'; const card = document.createElement('div'); card.className = 'qs-card'; card.innerHTML = `