// ==UserScript==
// @name Direct Image Uploader
// @namespace https://greasyfork.org/users/321857-anakunda
// @version 1.03
// @description Directly upload local / rehost remote image(s) to whatever dedicated image host by dropping/pasting them to target field
// @author Anakunda
// @match https://passthepopcorn.me/*
// @match https://*/torrents.php?id=*
// @match https://*/artist.php?id=*
// @match https://*/artist.php?action=edit&artistid=*
// @match https://*/reportsv2.php?action=report&id=*
// @match https://*/forums.php?action=new*
// @match https://*/forums.php?*action=viewthread*
// @match https://*/requests.php?action=view*
// @match https://*/collages.php?id=*
// @match https://*/collages.php?action=edit&collageid=*
// @match https://*/collages.php?action=comments&collageid=*
// @match https://*/collages.php?action=new
// @match http*://tracker.czech-server.com/upload2.php
// @match http*://tracker.czech-server.com/edit.php*
// @connect *
// @grant GM_xmlhttpRequest
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue
// @require https://greasyfork.org/scripts/401725-xhrlib/code/xhrLib.js
// @require https://greasyfork.org/scripts/394414-ua-resource/code/UA-resource.js
// @require https://greasyfork.org/scripts/401726-imagehostuploader/code/imageHostUploader.js
// ==/UserScript==
'use strict';
document.querySelectorAll('input#image').forEach(setInputHandlers);
document.querySelectorAll('input[name*="image"]').forEach(setInputHandlers);
Array.from(document.getElementsByTagName('textarea')).forEach(setTextAreahandlers);
if (document.URL.includes('/torrents.php?id=')) {
let a = document.querySelector('span.additional_add_artists > a');
if (a != null) a.addEventListener('click', function() {
document.querySelectorAll('input[name="image[]"]').forEach(setInputHandlers);
});
}
if (document.domain == 'tracker.czech-server.com') document.querySelectorAll('input[name="urlobr"]').forEach(setInputHandlers);
if (document.URL.includes('/reportsv2.php')) {
setReportHandlers();
var reportTypeSelect = document.querySelector('select#type');
if (reportTypeSelect != null) reportTypeSelect.addEventListener('change', setReportHandlers);
}
function setReportHandlers() {
setTimeout(function() {
['input#proofimages', 'input#image'].forEach(selector => { document.querySelectorAll(selector).forEach(setInputHandlers) });
document.querySelectorAll('textarea#extra').forEach(setTextAreahandlers);
}, 2000);
}
function coverPreview(input, imgUrl, size) {
var div, child = document.getElementById('cover-preview');
if (child == null) {
return;
// if (!(input instanceof HTMLElement) || input.parentNode.previousElementSibling == null) return;
// var elem = document.createElement('div');
// elem.style = 'padding-top: 10px; float: right; width: 90%;';
// child = document.createElement('img');
// child.id = 'cover-preview';
// elem.append(child);
// var div = document.createElement('div');
// div.id = 'cover-size';
// elem.append(div);
// input.parentNode.previousElementSibling.append(document.createElement('br'));
// input.parentNode.previousElementSibling.append(elem);
}
if ((div = div || document.getElementById('cover-size')) == null) return;
if (urlParser.test(imgUrl)) {
child.onload = function(evt) {
this.onload = null;
if (!this.naturalWidth || !this.naturalHeight) return; // invalid image
(size > 0 ? Promise.resolve(size) : getRemoteFileSize(imgUrl)).then(function(size) {
div.textContent = this.naturalWidth + '×' + this.naturalHeight + ' (' + formattedSize(size) + ')';
}.bind(this)).catch(reason => { div.textContent = this.naturalWidth + '×' + this.naturalHeight });
};
child.onerror = function(evt) {
this.onerror = null;
div.textContent = this.src = '';
console.warn('Image source cannot be updated:', evt, imgUrl);
};
child.src = imgUrl;
} else div.textContent = child.src = '';
}
function imageDataHandler(evt, data) {
if (!data) return true;
if (data.files.length > 0) {
if (!data.files[0].type.toLowerCase().startsWith('image/')) return true;
evt.target.disabled = true;
if (evt.target.hTimer) {
clearTimeout(evt.target.hTimer);
delete evt.target.hTimer;
}
evt.target.style.backgroundColor = '#800000';
let elem = evt.target, file = data.files[0], size = data.files[0].size;
uploadImages([file], evt.target).then(function(urls) {
elem.value = urls[0];
elem.style.backgroundColor = '#008000';
elem.style.color = 'white';
elem.hTimer = setTimeout(function() {
elem.style.backgroundColor = null;
elem.style.color = null;
delete elem.hTimer;
}, 10000);
coverPreview(elem, urls[0], size);
}).catch(function(error) {
elem.style.backgroundColor = null;
imageClear(evt);
alert(error);
}).then(function() { elem.disabled = false });
return false;
} else if (data.items.length > 0) {
verifyImageUrl((data.getData('text/uri-list') || data.getData('text/plain')).split(/\r?\n/)[0], true).then(function(imageUrl) {
evt.target.value = imageUrl;
coverPreview(evt.target, imageUrl);
if (imageUrl.toLowerCase().startsWith(ptpimgOrigin)) return;
evt.target.disabled = true;
rehostImages([imageUrl])
.then(urls => { if (urls.length > 0 && urls[0] != evt.target.value) evt.target.value = urls[0] })
.catch(e => { alert(e + ' (not rehosted)') })
.then(function() { evt.target.disabled = false });
}).catch(function(e) {
console.error(e);
alert(e);
});
return false;
}
return true;
}
function descDropHandler(evt) {
if (evt.dataTransfer == null || evt.shiftKey) return true;
if (evt.dataTransfer.files.length > 0) {
let images = [];
Array.from(evt.dataTransfer.files).forEach(function(file) {
switch (file.type) {
case 'image/png':
case 'image/jpeg':
case 'image/gif':
case 'image/bmp':
//case 'image/webp':
//case 'image/svg+xml':
images.push(file);
break;
}
});
if (images.length > 0) {
evt.target.disabled = true;
evt.target.style.background = '#FF000040 no-repeat center center url(' + ulImgData +')';
//evt.target.style.background = '#FF000040 no-repeat center center url(https://svgshare.com/i/H16.svg)';
let elem = evt.target;
uploadImages(images).then(urlHandler).catch(error => { alert(error) }).then(function() {
elem.style.background = null;
elem.disabled = false;
});
}
return false;
} else if (evt.dataTransfer.items.length > 0) {
let content = evt.dataTransfer.getData('text/uri-list');
if (content) verifyImageUrls(content.split(/\r?\n/), true).then(function(imageUrls) {
//if (auto_rehost_cover) {
evt.target.disabled = true;
rehostImages(imageUrls)
.then(urlHandler)
.catch(e => { alert(e + ' (not rehosted)') })
.then(function() { evt.target.disabled = false });
//} else urlHandler(content);
});
return false;
}
return true;
function urlHandler(urls) {
urls.forEach(function(url, ndx) {
if (url.length <= 0 || !urlParser.test(url)) return;
var phpBB = '[img]' + url + '[/img]';
if (evt.target.value.trimRight().length <= 0) evt.target.value = phpBB; else if (evt.ctrlKey) {
evt.target.value = evt.target.value.slice(0, evt.rangeOffset) + phpBB + evt.target.value.slice(evt.rangeOffset);
} else if (/\[img\]\[\/img\]/i.test(evt.target.value)) {
evt.target.value = RegExp.leftContext + phpBB + RegExp.rightContext;
} else {
evt.target.value = evt.target.value.trimRight().concat('\n\n', phpBB);
}
});
}
}
function imageUrlResolver(url) {
return urlResolver(url).then(url => verifyImageUrl(url).catch(function(reason) {
try { url = new URL(url) } catch(e) { return Promise.reject(e) }
if (url.hostname.endsWith('bandcamp.com')) return globalFetch(url)
.then(response => verifyImageUrl(response.document.querySelector('div#tralbumArt > a.popupImage').href));
else if (url.hostname.endsWith('.7digital.com')) return globalFetch(url)
.then(response => verifyImageUrl(response.document.querySelector('span.release-packshot-image > img[itemprop="image"]').src));
else if (url.hostname.startsWith('hdtracks.') || url.hostname.startsWith('www.hdtracks.')) return globalFetch(url)
.then(response => verifyImageUrl(response.document.querySelector('p.product-image > img').src));
else switch (url.hostname) {
case 'imgur.com':
return globalFetch(url).then(response => verifyImageUrl(response.document.querySelector('link[rel="image_src"]').href));
case 'jerking.empornium.ph':
if (!url.pathname.startsWith('/image/')) break;
return globalFetch(url)
.then(response => verifyImageUrl(response.document.querySelector('meta[property="og:image"]').content));
case 'malzo.com':
if (!url.pathname.startsWith('/im/')) break;
case 'postimg.cc':
return globalFetch(url)
.then(response => verifyImageUrl(response.document.querySelector('meta[property="og:image"]').content));
case 'pixhost.to':
if (!url.pathname.startsWith('/show/')) break;
return globalFetch(url).then(response => verifyImageUrl(response.document.querySelector('img#image').src));
case 'imgbb.com': case 'ibb.co':
return globalFetch(url)
.then(response => verifyImageUrl(response.document.querySelector('div#image-viewer-container img').src));
case 'www.imagevenue.com':
return globalFetch(url, { headers: { Referer: 'http://www.imagevenue.com/' } })
.then(response => verifyImageUrl((response.document.querySelector('div.card img')
|| response.document.querySelector('img#thepic')).src));
case 'www.imagebam.com':
if (!url.pathname.startsWith('/image//')) break;
return globalFetch(url, { headers: { Referer: 'http://www.imagebam.com/' } })
.then(response => verifyImageUrl(response.document.querySelector('meta[property="og:image"]').content));
case 'redacted.ch':
if (url.pathname != '/image.php') break;
return globalFetch(url, { method: 'HEAD' }).then(response => verifyImageUrl(response.finalUrl));
case 'demo.cloudimg.io':
if (!/\b(https?:\/\/\S+)$/.test(url.pathname.concat(url.search, url.hash))) break;
var resolved = RegExp.$1;
if (/\b(?:https?):\/\/(?:\w+\.)*discogs\.com\//i.test(resolved)) break;
return imageResolver(resolved);
case 'fastpic.ru':
if (url.pathname.startsWith('/view/'))
return globalFetch(url).then(response => imageUrlResolver(response.document.querySelector('a.img-a').href));
if (url.pathname.startsWith('/fullview/'))
return globalFetch(url).then(response => verifyImageUrl(response.document.getElementById('image').src));
break;
case 'radikal.ru': case 'a.radikal.ru':
return globalFetch(url).then(response => verifyImageUrl(response.document.querySelector('div.mainBlock img').src));
case 'imageban.ru': case 'ibn.im':
return globalFetch(url)
.then(response => verifyImageUrl(response.document.getElementById('img_main').src /* dataset.original */));
// music-related
case 'www.musicbrainz.org': case 'musicbrainz.org':
if (!['release', 'release-group'].some(branch => url.pathname.includes('/'.concat(branch, '/')))) break;
return globalFetch(url).then(function(response) {
var node = response.document.querySelector('a.artwork-image');
if (node != null) return verifyImageUrl(node.href);
return (node = response.document.querySelector('div.cover-art > img')) != null ?
verifyImageUrl(node.src) : Promise.reject('Cover missing');
});
case 'music.apple.com':
if (!/^https?:\/\/(?:\w+\.)*apple\.com\/.*\/(\d+)(?=$|\?)/i.test(url)) break;
return globalFetch(url).then(function(response) {
var meta = response.document.querySelector('meta[property="og:image"][content]');
if (meta == null || !meta.content) return Promise.reject('Cover missing');
return verifyImageUrl(meta.content.replace(/\/\d+x\d+\w*(?=\.\w+$)/, '/100000x100000-999'))
.catch(reason => verifyImageUrl(meta.content));
});
case 'www.deezer.com': case 'deezer.com':
return globalFetch(url).then(function(response) {
var meta = response.document.querySelector('meta[property="og:image"][content]');
if (meta == null || !meta.content) return Promise.reject('Cover missing');
return verifyImageUrl(meta.content.replace(/\/\d+x\d+\w*(?=\.\w+$)/, '/1400x1400-000000-100-0-0'))
.catch(reason => verifyImageUrl(meta.content));
});
case 'www.qobuz.com': case 'qobuz.com':
if (!url.pathname.includes('/album/')) break;
return globalFetch(url).then(function(response) {
var img = response.document.querySelector('div.album-cover > img');
if (img == null) return Promise.reject('Cover missing');
return verifyImageUrl(img.src.replace(/_\d{3}(?=\.\w+$)/, '_max')).catch(reason => verifyImageUrl(img.src));
});
case 'www.prestomusic.com': case 'prestomusic.com':
if (!url.pathname.includes('/products/')) break;
return globalFetch(url)
.then(response => verifyImageUrl(response.document.querySelector('div.c-product-block__aside > a').href.replace(/\?\d+$/)));
case 'www.bontonland.cz':case 'bontonland.cz':
return globalFetch(url)
.then(response => verifyImageUrl(response.document.querySelector('a.detailzoom').href));
case 'www.nativedsd.com':case 'nativedsd.com':
if (!url.pathname.includes('/albums/')) break;
return globalFetch(url)
.then(response => verifyImageUrl(response.document.querySelector('a#album-cover').href));
case 'www.prostudiomasters.com': case 'prostudiomasters.com':
if (!url.pathname.includes('/album/')) break;
return globalFetch(url).then(function(response) {
var a = response.document.querySelector('img.album-art');
return verifyImageUrl(a.currentSrc || a.src);
});
case 'www.e-onkyo.com': case 'e-onkyo.com':
if (!url.pathname.includes('/album/')) break;
return globalFetch(url).then(function(response) {
var a = response.document.querySelector('figure > a.colorbox');
return verifyImageUrl(new URL(response.finalUrl).origin.concat(a.pathname));
})
case 'store.acousticsounds.com':
return globalFetch(url).then(function(response) {
var link = response.document.querySelector('div#detail > link[rel="image_src"]');
return verifyImageUrl(link.href.replace(/\/medium\//i, '/large/'))
.catch(reason => verifyImageUrl(link.href));
});
case 'www.indies.eu': case 'indies.eu':
if (!url.pathname.includes('/alba/')) break;
return globalFetch(url)
.then(response => verifyImageUrl(response.document.querySelector('div.obrazekDetail > img').src));
case 'www.beatport.com': case 'beatport.com':
if (!url.pathname.includes('/release/')) break;
return globalFetch(url)
.then(response => verifyImageUrl(response.document.querySelector('div > img.interior-release-chart-artwork').src));
case 'www.supraphonline.cz': case 'supraphonline.cz':
if (!url.pathname.includes('/album/')) break;
return globalFetch(url)
.then(response => verifyImageUrl(response.document.querySelector('meta[itemprop="image"]').content.replace(/\?.*$/, '')));
case 'vgmdb.net':
if (!url.pathname.includes('/album/')) break;
return globalFetch(url).then(function(response) {
var div = response.document.querySelector('div#coverart');
return /\b(?:url)\s*\(\"(.*)"\)/i.test(div.style['background-image']) ?
verifyImageUrl(RegExp.$1) : Promise.reject('Cover missing');
});
case 'www.ototoy.jp': case 'ototoy.jp':
return globalFetch(url).then(function(response) {
var img = response.document.querySelector('div#tralbumArt > a.popupImage');
return verifyImageUrl(img.dataset.src || img.src);
});
case 'music.yandex.ru':
if (!url.pathname.includes('/album/')) break;
return globalFetch(url).then(function(response) {
var script = response.document.querySelector('script.light-data');
if (script == null) return Promise.reject('Invalid page structure');
return verifyImageUrl(JSON.parse(script.text).image);
});
// movie-related
case 'www.imdb.com': case 'imdb.com':
if (!['title/tt', 'name/nm'].some(cat => url.pathname.startsWith('/' + cat))) break;
return globalFetch(url).then(function(response) {
var script = response.document.head.querySelector(':scope > script[type="application/ld+json"]');
var image = JSON.parse(script.text).image;
return verifyImageUrl(image);
}).catch(reason => Promise.reject('No image for this item'));
case 'www.themoviedb.org': case 'themoviedb.org':
if (!['movie', 'person'].some(cat => url.pathname.startsWith('/' + cat + '/'))) break;
return globalFetch(url).then(function(response) {
var node = response.document.querySelector('meta[property="og:image"][content]');
return verifyImageUrl(node.content.replace(/\/p\/\w+\//i, '/p/original/')).catch(function(reason) {
node = response.document.querySelector('div.image_content > img');
return verifyImageUrl((node.dataset.src || node.src).replace(/\/p\/\w+\//i, '/p/original/'));
}).catch(reason => Promise.reject('No image for this item'));
});
case 'www.omdb.org': case 'omdb.org':
if (!['movie', 'person'].some(cat => url.pathname.startsWith('/' + cat + '/'))) break;
return globalFetch(url).then(function(response) {
var node = response.document.querySelector('meta[property="og:image"][content]');
return verifyImageUrl(node.content).catch(reason => Promise.reject('No image for this item'));
});
case 'www.thetvdb.com': case 'thetvdb.com':
if (!['movies', 'series', 'people'].some(cat => url.pathname.startsWith('/' + cat + '/'))) break;
return globalFetch(url).then(response => verifyImageUrl(response.document.querySelector('img.img-responsive').src));
case 'www.rottentomatoes.com': case 'rottentomatoes.com':
if (!['m', 'celebrity', 'tv'].some(cat => url.pathname.startsWith('/' + cat + '/'))) break;
return globalFetch(url).then(response => verifyImageUrl(response.document.querySelector('meta[property="og:image"]').content));
case 'www.bcdb.com': case 'bcdb.com':
if (!['cartoon'].some(cat => url.pathname.startsWith('/' + cat + '/'))) break;
return globalFetch(url).then(response =>
verifyImageUrl(document.location.protocol.concat(response.document.querySelector('meta[property="og:image"]').content)));
case 'www.boxofficemojo.com': case 'boxofficemojo.com':
if (!['releasegroup'].some(cat => url.pathname.startsWith('/' + cat + '/'))) break;
return globalFetch(url).then(response => verifyImageUrl(response.document.querySelector('div.mojo-primary-image img').src));
case 'www.metacritic.com': case 'metacritic.com':
return globalFetch(url).then(response => verifyImageUrl(response.document.querySelector('meta[property="og:image"]').content));
case 'www.csfd.cz': case 'csfd.cz':
//if (!url.pathname.includes('/film/')) break;
return globalFetch(url).then(function(response) {
var img = response.document.querySelector('img.film-poster');
return img != null ? verifyImageUrl(img.src.replace(/\?.*$/, '')) : Promise.reject('Invalid page structure');
});
case 'www.fdb.cz': case 'fdb.cz':
//if (!url.pathname.startsWith('/film/')) break;
return globalFetch(url).then(function(response) {
var a = response.document.querySelector('a.boxPlakaty');
if (a == null) return Promise.reject('Invalid page structure');
a.hostname = 'www.fdb.cz';
return globalFetch(a.href).then(function(response) {
var imgs = response.document.querySelectorAll('span#popup_plakaty > img');
return imgs.length > 0 ? imgs[0].src : Promise.reject('Cover missing');
});
});
case 'discogs.com': case 'www.discogs.com':
if (!['release', 'master', 'artist'].some(branch => url.pathname.includes('/'.concat(branch, '/')))) break;
default:
return globalFetch(url, { headers: { 'Referer': url.origin } }).then(function(response) {
var meta = response.document.querySelector('meta[property="og:image"][content]')
|| response.document.querySelector('meta[itemprop="image"][content]')
|| response.document.querySelector('meta[name="og:image"][content]');
return meta != null && meta.content ? verifyImageUrl(meta.content)
: Promise.reject('This URL cannot be resolved to direct image link:\n\n' + url);
});
}
return Promise.reject('This URL cannot be resolved to direct image link:\n\n' + url);
}));
}