// ==UserScript==
// @name Pinterest Ultra Assistant V6.5 (Ghost Stable)
// @namespace http://tampermonkey.net/
// @version 6.5
// @description Ghost Engine: One-Click Originals, AI 2x Sharpen, and Source Finder. Optimized for maximum stability.
// @author Pi Xiao
// @match https://*.pinterest.com/*
// @grant GM_openInTab
// @grant GM_setClipboard
// @license MIT
// @downloadURL none
// ==/UserScript==
(function() {
'use strict';
const BRIDGE_PAGE = "https://meishubiji.cn/ai-processing-center/";
// --- 算法与颜色逻辑 (保持 V6.4 核心) ---
function getColorDist(hex1, hex2) {
const r1 = parseInt(hex1.slice(1,3), 16), g1 = parseInt(hex1.slice(3,5), 16), b1 = parseInt(hex1.slice(5,7), 16);
const r2 = parseInt(hex2.slice(1,3), 16), g2 = parseInt(hex2.slice(3,5), 16), b2 = parseInt(hex2.slice(5,7), 16);
return Math.sqrt((r1-r2)**2 * 0.3 + (g1-g2)**2 * 0.59 + (b1-b2)**2 * 0.11);
}
function rgbToHex(r, g, b) {
return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase();
}
function getVividPalette(img) {
try {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 100; canvas.height = 100;
ctx.drawImage(img, 0, 0, 100, 100);
const data = ctx.getImageData(0, 0, 100, 100).data;
let colorMap = {};
for (let i = 0; i < data.length; i += 12) {
const r = data[i], g = data[i+1], b = data[i+2], a = data[i+3];
if (a < 128) continue;
const saturation = Math.max(r, g, b) - Math.min(r, g, b);
const brightness = (r + g + b) / 3;
let bias = (saturation > 40) ? 1 : 0.1;
if (brightness < 30 || brightness > 230) bias = 0.2;
const hex = rgbToHex(r, g, b);
colorMap[hex] = (colorMap[hex] || 0) + (Math.pow(saturation, 2) * bias + 1);
}
const sortedColors = Object.keys(colorMap).sort((a, b) => colorMap[b] - colorMap[a]);
const final = [];
for (const c of sortedColors) {
if (final.length >= 6) break;
if (final.every(ec => getColorDist(ec, c) > 50)) final.push(c);
}
return final;
} catch(e) { return []; }
}
// --- 预览窗逻辑 ---
async function processAndShow(imgUrl) {
const originalUrl = imgUrl.replace(/\/(236x|474x|564x|736x|1200x)\//, '/originals/').replace(/\.webp$/, '.jpg');
const overlay = document.createElement('div');
overlay.style = "position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.97);z-index:2147483647;display:flex;flex-direction:column;align-items:center;justify-content:center;color:white;font-family:sans-serif;cursor:zoom-out;";
overlay.innerHTML = '
';
overlay.onclick = () => overlay.remove();
document.body.appendChild(overlay);
const img = new Image();
img.crossOrigin = "Anonymous";
img.src = originalUrl;
img.onload = function() {
const palette = getVividPalette(img);
overlay.innerHTML = "";
const container = document.createElement('div');
container.style = "text-align:center;width:95%;height:90vh;display:flex;flex-direction:column;cursor:default;";
container.onclick = (e) => e.stopPropagation();
const scrollBox = document.createElement('div');
scrollBox.style = "overflow:auto;border:1px solid #333;border-radius:12px;flex:1;background:#050505;display:flex;align-items:center;justify-content:center;";
const pImg = document.createElement('img');
pImg.src = originalUrl;
pImg.style = "max-width:200%;image-rendering:-webkit-optimize-contrast;filter:contrast(1.05);";
scrollBox.appendChild(pImg);
const bar = document.createElement('div');
bar.style = "padding:25px;display:flex;flex-direction:column;align-items:center;gap:20px;background:#0a0a0a;";
let palHTML = 'Accents:';
palette.forEach(c => { palHTML += `
`; });
palHTML += '
';
bar.innerHTML = palHTML + ``;
container.appendChild(scrollBox);
container.appendChild(bar);
overlay.appendChild(container);
overlay.querySelectorAll('.px-c').forEach(el => {
el.onclick = () => { GM_setClipboard(el.dataset.hex); el.style.borderColor = "#fff"; setTimeout(()=>el.style.borderColor="#222",500); };
});
overlay.querySelector('#px-go').onclick = () => window.open(`${BRIDGE_PAGE}?url=${encodeURIComponent(originalUrl)}`, '_blank');
};
img.onerror = () => { window.open(originalUrl, '_blank'); overlay.remove(); };
}
// --- 核心注入逻辑:Ghost 模式 ---
function injectButtons() {
try {
const images = document.querySelectorAll('img[src*="pinimg.com"]');
images.forEach(img => {
if (img.width < 100 || img.closest('.px-helper-bar')) return;
// 更稳健的容器探测
const container = img.closest('[data-test-id="pin-visual-wrapper"]') ||
img.closest('[data-test-id="visual-content-container"]') ||
img.closest('.XiG') || img.parentElement;
if (container && container.tagName !== 'BODY') {
// 仅在必要时修改定位,避免触发 Pinterest 全量重绘
if (window.getComputedStyle(container).position === 'static') {
container.style.setProperty('position', 'relative', 'important');
}
const bar = document.createElement('div');
bar.className = 'px-helper-bar';
bar.style = "position:absolute;top:8px;left:8px;z-index:999;display:flex;gap:4px;opacity:0;transition:0.2s;pointer-events:auto;";
container.addEventListener('mouseenter', () => bar.style.opacity = "1");
container.addEventListener('mouseleave', () => bar.style.opacity = "0");
const btnS = 'color:white;border:none;border-radius:4px;cursor:pointer;padding:4px 8px;font-weight:bold;font-size:9px;box-shadow:0 2px 5px rgba(0,0,0,0.3);white-space:nowrap;';
const b1 = document.createElement('button'); b1.innerHTML = '🪄 2x HD'; b1.style = btnS + 'background:#00BFFF;';
b1.onclick = (e) => { e.preventDefault(); e.stopPropagation(); processAndShow(img.src); };
const b2 = document.createElement('button'); b2.innerHTML = '🖼️ Originals'; b2.style = btnS + 'background:#E60023;';
b2.onclick = (e) => { e.preventDefault(); e.stopPropagation(); window.open(img.src.replace(/\/(236x|474x|564x|736x)\//, '/originals/'), '_blank'); };
const b3 = document.createElement('button'); b3.innerHTML = '🔍 Source'; b3.style = btnS + 'background:#34a853;';
b3.onclick = (e) => { e.preventDefault(); e.stopPropagation(); window.open(`https://lens.google.com/uploadbyurl?url=${encodeURIComponent(img.src.replace(/\/(236x|474x|564x|736x)\//, '/originals/'))}`, '_blank'); };
bar.append(b1, b2, b3);
container.appendChild(bar);
}
});
} catch (e) { console.error("Injection error skipped."); }
}
// --- 启动流程:避开加载高峰 ---
window.addEventListener('load', () => {
// 等待 2 秒,确保 Pinterest 的 JS 引擎已经跑顺了
setTimeout(() => {
injectButtons();
const obs = new MutationObserver(injectButtons);
obs.observe(document.body, { childList: true, subtree: true });
setInterval(injectButtons, 3000);
}, 2000);
});
})();