您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
lolzPic
// ==UserScript== // @name lolz @pic // @namespace lolzPic // @description lolzPic // @version 1.0 // @match https://lolz.live/* // @grant GM_xmlhttpRequest // @grant GM_addStyle // ==/UserScript== (() => { 'use strict'; const API_KEY = ''; const CX_ID = ''; const getEditor = () => document.activeElement?.closest('[contenteditable="true"]') || document.querySelector('[contenteditable="true"]'); const LOLZ_STYLES = ` .lpic-scroll { position: absolute; z-index: 9999; background: #0d0d0d; border: 1px solid #2BAD72; border-radius: 6px; width: min-content; max-height: 306px; overflow-y: auto; overflow-x: hidden; padding: 6px; box-shadow: 0 4px 12px rgba(0,0,0,.6); left: var(--lp-left); top: var(--lp-top); font-family: "JetBrains Mono", "Courier New", monospace; display: grid; grid-template-columns: repeat(3, 90px); gap: 8px; } .lpic-cell { position: relative; width: 90px; height: 90px; } .lpic-item { width: 100%; height: 100%; object-fit: cover; border-radius: 4px; cursor: pointer; transition: transform .15s; } .lpic-item:hover { transform: scale(1.08); outline: 2px solid #2BAD72; } .lpic-loupe { position: absolute; top: 4px; right: 4px; background: rgba(0,0,0,.6); color: #2BAD72; font-size: 14px; line-height: 20px; width: 20px; height: 20px; border-radius: 50%; text-align: center; cursor: pointer; z-index: 2; opacity: 0; transition: opacity .2s; pointer-events: none; } .lpic-cell:hover .lpic-loupe { opacity: 1; pointer-events: auto; } .lpic-preview-overlay { position: fixed; inset: 0; z-index: 10000; background: rgba(0,0,0,.75); display: flex; align-items: center; justify-content: center; cursor: pointer; } .lpic-preview-img { width: 300px; height: 300px; object-fit: contain; border: 2px solid #2BAD72; border-radius: 8px; } `; GM_addStyle(LOLZ_STYLES); let menu = null; let inputTimeout = null; let currentQuery = ''; let loadedPages = 0; let totalResults = 0; let loadingMore = false; let previewOverlay = null; function createMenu(editor) { if (menu) menu.remove(); menu = document.createElement('div'); menu.className = 'lpic-scroll'; const rect = editor.getBoundingClientRect(); menu.style.setProperty('--lp-left', `${rect.left + window.scrollX}px`); menu.style.setProperty('--lp-top', `${rect.top + window.scrollY - 320}px`); document.body.appendChild(menu); menu.addEventListener('scroll', () => { if (!loadingMore && totalResults > menu.children.length && menu.scrollTop + menu.clientHeight >= menu.scrollHeight - 40) { loadNextPage(editor); } }); return menu; } function loadNextPage(editor) { if (loadingMore) return; loadingMore = true; const start = loadedPages * 10 + 1; GM_xmlhttpRequest({ method: 'GET', url: `https://www.googleapis.com/customsearch/v1?key=${API_KEY}&cx=${CX_ID}&q=${encodeURIComponent(currentQuery)}&searchType=image&num=10&safe=off&start=${start}`, onload: resp => { try { const data = JSON.parse(resp.responseText); totalResults = parseInt(data.searchInformation?.totalResults || 0); loadedPages++; (data.items || []).forEach(item => appendImage(item.link)); } catch { appendFallback(); } loadingMore = false; }, onerror: () => { appendFallback(); loadingMore = false; } }); function appendFallback() { for (let i = 0; i < 9; i++) appendImage(`https://picsum.photos/300?random=${Math.random()}`); } function appendImage(url) { const cell = document.createElement('div'); cell.className = 'lpic-cell'; const img = document.createElement('img'); img.className = 'lpic-item'; img.src = url; img.addEventListener('click', () => insert(url)); const loupe = document.createElement('span'); loupe.className = 'lpic-loupe'; loupe.textContent = '🔍'; loupe.title = 'Предпросмотр'; loupe.addEventListener('click', e => { e.stopPropagation(); showPreview(url); }); cell.appendChild(img); cell.appendChild(loupe); menu.appendChild(cell); } } function showPreview(src) { if (previewOverlay) previewOverlay.remove(); previewOverlay = document.createElement('div'); previewOverlay.className = 'lpic-preview-overlay'; const img = document.createElement('img'); img.className = 'lpic-preview-img'; img.src = src; previewOverlay.appendChild(img); document.body.appendChild(previewOverlay); previewOverlay.addEventListener('click', hidePreview); document.addEventListener('keydown', escClose); function escClose(e) { if (e.key === 'Escape') { hidePreview(); document.removeEventListener('keydown', escClose); } } } function hidePreview() { previewOverlay?.remove(); previewOverlay = null; } function insert(url) { const ed = getEditor(); if (!ed) return; const text = ed.textContent; const match = text.match(/@pic\s+([^\s]+)/); if (!match) return; ed.textContent = text.replace(match[0], `[IMG]${url}[/IMG] `); const sel = window.getSelection(); sel.selectAllChildren(ed); sel.collapseToEnd(); menu?.remove(); } document.addEventListener('click', e => { if (menu && !menu.contains(e.target)) menu.remove(); }); document.addEventListener('input', e => { const ed = getEditor(); if (!ed) return; const text = ed.textContent; const m = text.match(/@pic\s+([^\s]+)/); if (!m) { menu?.remove(); return; } currentQuery = m[1]; loadedPages = 0; totalResults = 0; clearTimeout(inputTimeout); inputTimeout = setTimeout(() => { createMenu(ed); loadNextPage(ed); }, 500); }); })();