Greasy Fork

RED Cover Inspector

Adds cover sticker if needs updating for unsupported host / big size / small resolution

目前为 2021-03-23 提交的版本。查看 最新版本

// ==UserScript==
// @name         RED Cover Inspector
// @namespace    https://greasyfork.org/users/321857-anakunda
// @version      1.03.0
// @description  Adds cover sticker if needs updating for unsupported host / big size / small resolution
// @author       Anakunda
// @copyright    2020, Anakunda (https://greasyfork.org/users/321857-anakunda)
// @license      GPL-3.0-or-later
// @match        https://redacted.ch/torrents.php?id=*
// @match        https://redacted.ch/artist.php?id=*
// @connect      *
// @grant        GM_xmlhttpRequest
// @grant        GM_getValue
// @grant        GM_setValue
// ==/UserScript==

const httpParser = /^(https?:\/\/.+)*$/i;

function getRemoteFileSize(url, forced = true) {
	return httpParser.test(url) ? new Promise(function(resolve, reject) {
		let size, abort = GM_xmlhttpRequest({ method: forced ? 'GET' : 'HEAD', url: url, responseType: 'blob',
		 onreadystatechange: function(response) {
			 if (size >= 0 || response.readyState < XMLHttpRequest.HEADERS_RECEIVED) return;
			 if (/^(?:Content-Length)\s*:\s*(\d+)\b/im.test(response.responseHeaders) && (size = parseInt(RegExp.$1)) >= 0)
				 resolve(size);
			 else if (!forced) reject(undefined); else return;
			 abort.abort();
		 },
		 onload: function(response) { // fail-safe
			 if (size >= 0) return;
			 if (response.status < 200 || response.status >= 400) reject('File not accessible');
			 resolve(response.responseText.length);
// 			 console.time('GM_xmlhttpRequest response size getter');
// 			 size = response.response.size; // response.responseText.length;
// 			 console.timeEnd('GM_xmlhttpRequest response size getter');
// 			 console.debug('response.size:', size, 'responseText.length:', response.responseText.length);
// 			 resolve(size);
		 },
		 onerror: response => { reject('File not accessible') },
		 ontimeout: response => { reject('File not accessible') },
		});
	}) : Promise.reject('getRemoteFileSize: parameter not valid URL');
}

function formattedSize(size) {
  return size >= 0 ? size < 1024**1 ? Math.round(size) + ' B'
		: size < 1024**2 ? (Math.round(size * 10 / 2**10) / 10) + ' KiB'
		: size < 1024**3 ? (Math.round(size * 100 / 2**20) / 100) + ' MiB'
		: size < 1024**4 ? (Math.round(size * 100 / 2**30) / 100) + ' GiB'
		: size < 1024**5 ? (Math.round(size * 100 / 2**40) / 100) + ' TiB'
		: (Math.round(size * 100 / 2**50) / 100) + ' PiB' : NaN;
}

let acceptableCoverSize = GM_getValue('acceptable_cover_size');
if (!(acceptableCoverSize >= 0)) GM_setValue('acceptable_cover_size', acceptableCoverSize = 2048);
let acceptableCoverResolution = GM_getValue('acceptable_cover_resolution');
if (!(acceptableCoverResolution >= 0)) GM_setValue('acceptable_cover_resolution', acceptableCoverResolution = 200);

document.querySelectorAll('div#covers p > img, div.box_image > div > img').forEach(function(img) {
  let imgSrc = img.dataset.gazelleTempSrc || img.src;
  if (imgSrc.startsWith(document.location.origin) && imgSrc.includes('/static/common/noartwork/')) return;
	if (imgSrc.startsWith('https://i.imgur.com/')) imgSrc = imgSrc.replace(/\/(\w{7,})m\.(\w+)$/, '/$1.$2');
	console.debug('imgSrc:', imgSrc);
  getRemoteFileSize(imgSrc).catch(function(reason) {
		console.warn('Failed to get remote image size (' + imgSrc + '):', reason);
		return undefined;
  }).then(function(size) {
		const span = (content, isOK = false) => (isOK ? '<span>' : '<span style="color: yellow;">') + content + '</span>',
					isProxied = imgSrc.startsWith(document.location.origin + '/image.php?'),
					isPreferredHost = imgSrc.startsWith('https://ptpimg.me'),
					isInvalid = isProxied && (size < 2 * 2**10 && img.naturalWidth == 400 && img.naturalHeight == 100 || size == 503),
					isSizeOK = acceptableCoverSize == 0 || size <= acceptableCoverSize * 2**10,
					isResolutionOK = acceptableCoverResolution == 0
						|| (!img.naturalWidth || img.naturalWidth >= acceptableCoverResolution)
						&& (!img.naturalHeight || img.naturalHeight >= acceptableCoverResolution);
		if (isPreferredHost && isSizeOK && isResolutionOK) return;
		let div = document.createElement('div');
		div.style = 'color: white; border: 1px solid whitesmoke; background-color: #ae2300; ' +
			'position: relative; font: 700 8pt "Segoe UI"; padding: 1px 5px;';
		if (!isInvalid) {
			div.style.opacity = 0.8;
			div.style.float = 'right';
			div.style.right = '7px'; div.style.bottom = '25px';
			div.innerHTML = span(formattedSize(size), isSizeOK) + ' / ' +
				span(img.naturalWidth + '×' + img.naturalHeight, isResolutionOK);
			if (isProxied) div.innerHTML = span('PROXY') + ' / ' + div.innerHTML;
				else if (!isPreferredHost) div.innerHTML = span('XTRN') + ' / ' + div.innerHTML;
		} else {
			div.style.bottom = '3px';
			div.innerHTML = span('INVALID');
		}
		img.insertAdjacentElement('afterend', div);
		if (isInvalid) img.remove();
	});
});