FIX Pinterest - Save Original Image

Pinterest - Save Original Image frin haofong, but fixed NOW ON CHROME

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         FIX Pinterest - Save Original Image
// @namespace    http://tampermonkey.net/
// @version      6.0.0
// @description  Pinterest - Save Original Image frin haofong, but fixed NOW ON CHROME
// @author       creve (and tg:@letsalllovelain78, ty for BIG IMPROVEMENTS ON THIS)
// @include      https://*.pinterest.tld/*
// @grant        GM_download
// @run-at       document-end

// @noframes
// @license      MIT
// ==/UserScript==

(function() {
	'use strict';

	let currentHoveredElement = null;

	function handleMouseOver(event) {
		currentHoveredElement = event.target;
	}

	function findNearestImage(element) {
		if (element.tagName === 'IMG' && element.width > 50) {
			return element;
		}

		const imgInside = element.querySelector('img[srcset], img[src]');
		if (imgInside && imgInside.width > 50) {
			return imgInside;
		}

		let pinContainer = element;
		for (let i = 0; i < 5 && pinContainer; i++) {
			pinContainer = pinContainer.parentElement;

			if (pinContainer) {
				const pinImage = pinContainer.querySelector('img[srcset], img[src]');
				if (pinImage && pinImage.width > 50) {
					return pinImage;
				}
			}
		}

		return null;
	}

	function getOriginalImageUrl(imgElement) {
		if (!imgElement) return null;

		if (imgElement.srcset) {
			const srcsetParts = imgElement.srcset.split(',');
			let largestImageUrl = '';
			let largestSize = 0;

			for (const part of srcsetParts) {
				const [url, size] = part.trim().split(' ');
				const numericSize = parseInt(size);

				if (numericSize > largestSize) {
					largestSize = numericSize;
					largestImageUrl = url;
				}
			}

			if (largestImageUrl) {
				return largestImageUrl;
			}
		}

		if (imgElement.src) {
			let originalUrl = imgElement.src;

			originalUrl = originalUrl.replace(/\/\d+x\//, '/originals/');

			return originalUrl;
		}

		return null;
	}

	function getPinTitle(imgElement) {
		let container = imgElement;
		for (let i = 0; i < 8 && container; i++) {
			container = container.parentElement;

			if (container) {
				const titleElement = container.querySelector('h1, h2, h3, [data-test-id="pin-title"], div[title]');
				if (titleElement && titleElement.textContent) {
					return titleElement.textContent.trim().replace(/[/\\?%*:|"<>]/g, '-').substring(0, 50);
				}

				if (imgElement.alt && imgElement.alt.length > 3) {
					return imgElement.alt.trim().replace(/[/\\?%*:|"<>]/g, '-').substring(0, 50);
				}
			}
		}

		if (document.querySelector('div[role="dialog"]')) {
			const modalTitle = document.querySelector('div[role="dialog"] h1') ||
							  document.querySelector('div[role="dialog"] [data-test-id="pin-title"]');
			if (modalTitle && modalTitle.textContent) {
				return modalTitle.textContent.trim().replace(/[/\\?%*:|"<>]/g, '-').substring(0, 50);
			}
		}

		const pinId = window.location.pathname.split('/').pop() || '';
		return 'pinterest-pin-' + (pinId || Date.now());
	}

	function downloadPinterestImage() {
		if (!currentHoveredElement) {
			console.log('Couldnt find hovered image');
			showNotification('Hover over an image and press "Z"', 'error');
			return;
		}

		const imgElement = findNearestImage(currentHoveredElement);

		if (!imgElement) {
			console.log('Couldnt find hovered image');
			showNotification('Couldnt find hovered image', 'error');
			return;
		}

		const imageUrl = getOriginalImageUrl(imgElement);

		if (!imageUrl) {
			console.log('Couldnt parse image URL');
			showNotification('Couldnt parse image URL', 'error');
			return;
		}

		const fileName = getPinTitle(imgElement) + '.jpg';

		if (typeof GM_download !== 'undefined') {
			GM_download({
				url: imageUrl,
				name: fileName,
				onload: function() {
					console.log('Image downloaded successfully: ' + fileName);
					showNotification('Image downloaded: ' + fileName, 'success');
				},
				onerror: function(error) {
					console.error('Error while downloading:', error);
					showNotification('Error while downloading image', 'error');
				}
			});
		} else {
			const link = document.createElement('a');
			link.href = imageUrl;
			link.download = fileName;
			link.style.display = 'none';
			link.style.display = 'none';
			document.body.appendChild(link);
			link.click();
			setTimeout(() => {
				document.body.removeChild(link);
				showNotification('Image downloaded: ' + fileName, 'success');
			}, 100);
		}

		console.log('Donwloading iamge:', imageUrl);
	}

	function showNotification(message, type = 'info') {
		const existingNotification = document.getElementById('pinterest-downloader-notification');
		if (existingNotification) {
			document.body.removeChild(existingNotification);
		}

		const notification = document.createElement('div');
		notification.id = 'pinterest-downloader-notification';

		let backgroundColor = 'rgba(0, 0, 0, 0.7)';
		if (type === 'success') backgroundColor = 'rgba(0, 128, 0, 0.8)';
		if (type === 'error') backgroundColor = 'rgba(200, 0, 0, 0.8)';

		notification.style.cssText = `
			position: fixed;
			bottom: 20px;
			right: 20px;
			background-color: ${backgroundColor};
			color: white;
			padding: 12px 18px;
			border-radius: 5px;
			z-index: 999999;
			font-size: 14px;
			font-family: Arial, sans-serif;
			box-shadow: 0 2px 5px rgba(0,0,0,0.3);
			max-width: 300px;
			opacity: 1;
			transition: opacity 0.3s;
		`;
		notification.textContent = message;
		document.body.appendChild(notification);

		setTimeout(() => {
			notification.style.opacity = '0';
			setTimeout(() => {
				if (document.body.contains(notification)) {
					document.body.removeChild(notification);
				}
			}, 300);
		}, 3000);
	}

	function addHoverIndicator() {
		const indicator = document.createElement('div');
		indicator.id = 'pinterest-hover-indicator';
		indicator.style.cssText = `
			position: fixed;
			padding: 5px 10px;
			background-color: rgba(0, 0, 0, 0.7);
			color: white;
			border-radius: 3px;
			font-size: 12px;
			z-index: 999999;
			pointer-events: none;
			opacity: 0;
			transition: opacity 0.2s;
		`;
		indicator.textContent = 'Press "Z" to download';
		document.body.appendChild(indicator);

		document.addEventListener('mousemove', function(event) {
			const element = event.target;
			const imgElement = findNearestImage(element);

			if (imgElement) {
				indicator.style.left = (event.clientX + 15) + 'px';
				indicator.style.top = (event.clientY + 15) + 'px';
				indicator.style.opacity = '1';
			} else {
				indicator.style.opacity = '0';
			}
		});

		document.addEventListener('mouseout', function(event) {
			if (!event.relatedTarget) {
				indicator.style.opacity = '0';
			}
		});
	}

	document.addEventListener('keydown', function(event) {
		if ((event.key === 'z' || event.key === 'я') &&
			!(event.target.tagName === 'INPUT' ||
			  event.target.tagName === 'TEXTAREA' ||
			  event.target.isContentEditable)) {
			event.preventDefault();
			downloadPinterestImage();
		}
	});

	document.addEventListener('mouseover', handleMouseOver);

	addHoverIndicator();

	setTimeout(() => {
		showNotification('Pinterest Downloader active! Hover over a image and press "Z" to download', 'info');
	}, 2000);
})();