NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name Replace lightshot links
// @version 1.4.2
// @description Makes links to pictures from "Ligthshot" by direct
// @updateURL https://openuserjs.org/meta/iSkile/Replace_lightshot_links.meta.js
// @copyright 2017, iSkile (https://openuserjs.org/users/iSkile)
// @author iSkile
// @license MIT
// @run-at document-start
// @include *://*/*
// @connect prnt.sc
// @connect image.prntscr.com
// @grant GM_openInTab
// @grant GM_xmlhttpRequest
// ==/UserScript==
/* jshint -W097 */
'use strict';
function loadWithReferrer(imgUrl, url, cb) {
GM_xmlhttpRequest({
method: "GET",
url: imgUrl,
responseType: 'blob',
headers: {
'referer': url,
'origin': 'https://prnt.sc'
},
onload: function (resp) {
if (resp.status === 200) {
return cb(window.URL.createObjectURL(resp.response));
}
return loadWithProxy(url + '/direct', cb);
},
});
}
function loadWithProxy(url, cb) {
GM_xmlhttpRequest({
method: "POST",
url: url,
data: {
url,
},
responseType: 'blob',
onload: function (resp) {
cb(window.URL.createObjectURL(resp.response));
},
});
}
let tooltip = null;
function getViewportSize(doc) {
// Width : getViewportSize()[0]
// Height: getViewportSize()[1]
doc = doc || document;
var elem = doc.compatMode === 'CSS1Compat' ? doc.documentElement : doc.body;
return [elem.clientWidth, elem.clientHeight];
}
function Tooltip() {
this.el = null;
this.noLoadedAttr = 'data-load';
//this.maxWidth = this.maxHeight = 500; //px
this.maxWidth = getViewportSize()[0] / 2; //px
this.maxHeight = getViewportSize()[1] / 2; //px
this.imgSize = [this.maxWidth, this.maxHeight]; // w h, in px
this.mousePos = [0, 0]; //x y, last mouse position
this.init();
}
Tooltip.prototype.init = function () {
if (!this.el) {
let el = document.createElement('div');
el.style.cssText = `
position: fixed;
transition: all .2s linear;
z-index: 2147483647;
box-shadow: black 0px 0px 20px 1px;
display: flex;
align-items: center;
justify-content: center;
background: #000000;
overflow: hidden;`;
document.body.appendChild(el);
// hotfix
el.onclick = el.onmouseout = () => this.hide();
this.el = el;
this.hide();
}
return this.el;
};
Tooltip.prototype.resize = function (maxW, maxH) {
//console.log(this, maxW, maxH);
this.el.style.maxWidth = maxW + 'px';
this.el.style.maxHeight = maxH + 'px';
let w = this.el.offsetWidth;
let h = this.el.offsetHeight;
this.imgSize = [w, h];
};
Tooltip.prototype.move = function (x, y) {
const Space = 14; // margin in px
let w = getViewportSize()[0];
let h = getViewportSize()[1];
let elPos = [0, 0]; // x, y
this.mousePos = [x, y];
let newW = this.imgSize[0] + Space * 2 > w ? x - Space : this.imgSize[0];
let newH = this.imgSize[1] + Space * 2 > h ? y - Space : this.imgSize[1];
if (this.imgSize[0] != newW || this.imgSize[1] != newH) {
this.resize(newW, newH);
}
if (x + this.imgSize[0] + Space * 2 > w) {
elPos[0] = x - this.imgSize[0] - Space;
if (elPos[0] < 0) elPos[0] = Space;
}
else {
elPos[0] = x + Space;
}
if (y + this.imgSize[1] + Space * 2 > h) {
elPos[1] = y - this.imgSize[1] - Space;
if (elPos[1] < 0) elPos[1] = Space;
}
else {
elPos[1] = y + Space;
}
this.el.style.left = elPos[0] + 'px';
this.el.style.top = elPos[1] + 'px';
};
Tooltip.prototype.show = function (url, el) {
while (this.el.hasChildNodes()) {
this.el.removeChild(this.el.firstChild);
}
this.el.style.maxWidth = this.maxWidth + 'px';
this.el.style.maxHeight = this.maxHeight + 'px';
let img = document.createElement('img');
img.style.cssText = `
display: block;
max-width: 100%;
height: auto;
max-height: 100%;
margin-left: auto;
margin-right: auto;`;
img.onload = () => {
let w = this.el.offsetWidth;
let h = this.el.offsetHeight;
this.imgSize = [w, h];
this.move(this.mousePos[0], this.mousePos[1]);
this.el.style.opacity = 1;
};
img.onerror = () => {
let w = 16;
let h = 16;
this.imgSize = [w, h];
this.move(this.mousePos[0], this.mousePos[1]);
this.el.style.opacity = 1;
};
img.src = url;
this.el.appendChild(img);
this.el.style.display = 'flex';
};
Tooltip.prototype.hide = function (url) {
this.el.style.display = 'none';
this.el.style.opacity = 0;
};
function getRealUrl(el, cb) {
const LoadTimeout = 5000;
const UrlAttr = 'data-real-url';
const UrlLoadAttr = 'data-real-url-load';
const OldCursorAttr = 'data-old-cursor-name';
const Regex = /<meta property="og:image" content="(.*?)"\/>/g;
let url = el.href.replace('prntscr.com', 'prnt.sc');
let attrUrl = el.getAttribute(UrlAttr);
if (attrUrl) {
return cb(attrUrl);
}
else {
let oldCursorName = el.getAttribute(OldCursorAttr) || el.style.cursor;
el.setAttribute(OldCursorAttr, oldCursorName);
el.style.cursor = 'wait';
let hardOpen = setTimeout(() => {
el.removeAttribute(UrlLoadAttr);
cb(false);
}, LoadTimeout);
let startTs = +new Date();
if (el.getAttribute(UrlLoadAttr)) {
return;
}
el.setAttribute(UrlLoadAttr, true);
GM_xmlhttpRequest({
method: 'GET',
url: url,
onload: function (response) {
if (+new Date() - startTs >= LoadTimeout) {
return false;
}
clearTimeout(hardOpen);
if (response.status.toString().match(/^2/)) {
let img = Regex.exec(response.response);
//console.log(response.response, img);
if (img) {
let realURL = img[1];
loadWithReferrer(realURL, url, resp => {
realURL = resp;
el.setAttribute(UrlAttr, realURL);
el.removeAttribute(UrlLoadAttr);
el.style.cursor = el.getAttribute(OldCursorAttr);
cb(resp);
});
}
}
cb(false);
}
});
}
}
function replace(root) {
if (!root) return;
let links = root.querySelectorAll('a[href*="://prntscr.com/"], a[href*="://prnt.sc/"], a[href*="://www.prntscr.com/"], a[href*="://www.prnt.sc/"]');
for (let link of links) {
link.onclick = function (e) {
e.preventDefault();
GM_openInTab(this.href, false);
};
link.onmouseenter = function (e) {
getRealUrl(this, resp => {
if (resp) {
tooltip.move(e.x, e.y);
tooltip.show(resp, this);
}
});
//link.onmousemove = ev => tooltip.move(ev.x, ev.y);
link.onmouseout = () => tooltip.hide();
};
}
}
let pingBody = setInterval(() => {
if (document.body && document.links.length) {
clearInterval(pingBody);
tooltip = new Tooltip();
}
}, 5);
if (document.defaultView.parent == document.defaultView) { // frame test
// if (~['prnt.sc'].indexOf(location.hostname)) {
// let interval = setInterval(() => {
// if (document.body) {
// document.body.style.display = 'none';
// }
// let under_img = document.querySelector('.under-image>img'); //#screenshot-image , meta[property="og:image"]
// let img = document.querySelector('#screenshot-image')
// if (under_img) {
// if (under_img.src != location.href) {
// let url = img.src;
// clearInterval(interval);
// document.write(`Redirect to: <a href="${url}">${url}</a>`); //stop load page
// location.replace(url);
// }
// img.onerror = () => {
// document.body.style.display = '';
// clearInterval(interval);
// }
// }
// }, 1);
// }
var observer = new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
mutation.addedNodes.forEach(function (addedNode) {
if (addedNode.nodeType === 1) {
replace(addedNode);
}
});
});
});
observer.observe(document.documentElement, {
childList: true,
subtree: true
});
replace(document.body);
}