// ==UserScript==
// @name Pinterest Plus
// @namespace https://greasyfork.org/users/102866
// @description Show full size + working middle click to open new tab + open original image.
// @include https://*.pinterest.*/*
// @require https://code.jquery.com/jquery-3.6.0.min.js
// @author TiLied
// @version 0.6.00
// @grant GM_openInTab
// @grant GM_listValues
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue
// @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
// @grant GM.openInTab
// @grant GM.listValues
// @grant GM.getValue
// @grant GM.setValue
// @grant GM.deleteValue
// @downloadURL none
// ==/UserScript==
class PinterestPlus
{
constructor()
{
console.log("Pinterest Plus v" + GM.info.script.version + " initialization");
this.urls = [""];
this._FirstTime();
this._SetCSS();
this._HidePopup();
}
_SetCSS()
{
$("head").append($(""));
$("head").append($("").text("button.ppTrue \
{ \
border:2px solid black!important; \
} \
"));
$("head").append($("").text("#myBtn \
{ \
display: inherit;\
align-items: center;\
box-sizing: border-box;\
color:#fff;\
font-size: 16px;\
font-weight: 700;\
letter-spacing: -.4px;\
margin-top: -4px;\
border-style: solid;\
border-width: 0px;\
background-color: #e60023;\
border-radius: 24px;\
padding: 10px 14px;\
will-change: transform;\
margin-left: 8px;\
} \
"));
$("head").append($("").text("#myBtn:hover \
{ \
background-color: #ad081b;\
} \
"));
$("head").append($("").text("#pp_divFullSize \
{ \
z-index: 500;!important; \
justify-content: center;\
display: inherit; \
} \
"));
$("head").append($(""));
}
//Hide popup after scrolling
_HidePopup()
{
setTimeout(function ()
{
let button = $(" button[aria-label='close']");
if (button.length >= 1)
$(button).click();
let popup = $(" div[data-test-id='giftWrap']:parent");
console.log(popup);
console.log(button);
$(popup).attr("style", "display:none;");
}, 1500);
}
async _FirstTime()
{
if (this.HasValueGM("ppFullSize", false))
{
this.btnOn = await GM.getValue("ppFullSize");
}
//Console log prefs with value
console.log("*prefs:");
console.log("*-----*");
let vals = await GM.listValues();
//Find out that var in for block is not local... Seriously js?
for (let i = 0; i < vals.length; i++)
{
console.log("*" + vals[i] + ":" + await GM.getValue(vals[i]));
}
console.log("*-----*");
}
Main()
{
if (!document.URL.match("/pin/"))
return;
this.urls = [""];
let buttonDiv = document.createElement("div");
let buttonButton = document.createElement("button");
let buttonText = document.createTextNode("Full Size");
let parentDiv = document.querySelector("div[data-test-id='closeupActionBar']>div>div, div[data-test-id='UnauthBestPinCardBodyContainer']>div>div>div, div.UnauthStoryPinCloseupBody__container>div>div");
if (typeof parentDiv === "undefined" || parentDiv == null)
{
console.error("parentDiv:", parentDiv);
return;
}
buttonButton.appendChild(buttonText);
buttonDiv.appendChild(buttonButton);
buttonButton.id = "myBtn";
parentDiv.appendChild(buttonDiv);
//
let queryCloseup = $("div[data-test-id='pin']:first, div.Closeup");
if (typeof queryCloseup === "undefined" || queryCloseup == null || queryCloseup.length === 0)
{
console.error("div[data-test-id='pin']:first, div.Closeup:", queryCloseup);
return;
}
let div = document.querySelector("#pp_divFullSize");
if (div == null)
{
div = document.createElement("div");
div.id = "pp_divFullSize";
queryCloseup.prepend(div);
}
div.style.display = "none";
if (this.btnOn)
{
$(buttonButton).addClass("ppTrue");
}
//
this.Events(buttonButton);
this.Core(buttonButton);
this.UrlHandler();
}
Core(btn)
{
let time = Date.now();
let url = new URL(document.URL);
let regU = document.URL.match(/\/(\d+)\/|pin\/([\w].+\w+)\//);
let id = regU[1];
if (typeof id === "undefined")
id = regU[2];
if (typeof id === "undefined")
{
//TODO! not through request!
}
let urlRec = "https://" + url.host + "/resource/PinResource/get/?source_url=/pin/" + id + "/&data={%22options%22:{%22field_set_key%22:%22detailed%22,%22id%22:%22" + id + "%22},%22context%22:{}}&_=" + time;
$.get(urlRec, async function (r)
{
if (r["resource_response"]["status"] === "success")
{
console.log(r["resource_response"]["data"]);
let pin = r["resource_response"]["data"];
if (pin["videos"] != null)
{
let k0 = Object.keys(pin["videos"]["video_list"])[0];
pp.urls[0] = pin["videos"]["video_list"][k0]["url"];
$(btn).attr("title", "" + pin["videos"]["video_list"][k0]["width"] + "px x " + pin["videos"]["video_list"][k0]["height"] + "px");
return;
}
if (pin["story_pin_data"] != null)
{
let sp = pin["story_pin_data"]["pages"];
for (let i in sp)
{
if (pp.urls[0] === "")
{
pp.urls[0] = sp[i]["image"]["images"]["originals"]["url"];
continue;
}
pp.urls.push(sp[i]["image"]["images"]["originals"]["url"]);
}
return;
}
pp.urls[0] = pin["images"]["orig"]["url"];
$(btn).attr("title", "" + pin["images"]["orig"]["width"] + "px x " + pin["images"]["orig"]["height"] + "px");
if (pp.btnOn)
pp.Show(pp.urls[0]);
return;
} else
{
console.error(r);
}
}, "json")
.fail(function (e)
{
console.error(e);
});
}
Events(btn)
{
$(btn).on('mousedown', async function (e)
{
if ((e.which === 3))
{
if (pp.btnOn)
{
GM.setValue("ppFullSize", false);
$(btn).removeClass("ppTrue");
pp.btnOn = false;
} else
{
GM.setValue("ppFullSize", true);
$(btn).addClass("ppTrue");
pp.btnOn = true;
}
//console.log("right");
}
if ((e.which === 1))
{
pp.Show(pp.urls[0]);
$("#pp_divFullSize").toggle(500);
//console.log("left");
}
if ((e.which === 2))
{
for (let i in pp.urls)
{
GM.openInTab(pp.urls[i]);
}
//console.log("middle");
}
e.preventDefault();
});
}
Show(url)
{
let img = document.querySelector("#pp_img");
let div = document.querySelector("#pp_divFullSize");
if (img != null)
{
img.setAttribute("src", url);
} else
{
img = document.createElement("img");
img.id = "pp_img";
img.setAttribute("src", url);
div.prepend(img);
}
}
//Handler for url
UrlHandler()
{
this.oldHash = window.location.pathname;
this.Check;
var that = this;
var detect = function ()
{
if (that.oldHash !== window.location.pathname)
{
that.oldHash = window.location.pathname;
setTimeout(function () { pp.Main(); }, 1500);
}
};
this.Check = setInterval(function () { detect(); }, 250);
}
//Start
//async Methods/Functions GM_VALUE
async HasValueGM(nameVal, optValue)
{
var vals = await GM.listValues();
if (vals.length === 0)
{
if (optValue !== undefined)
{
GM.setValue(nameVal, optValue);
return true;
} else
{
return false;
}
}
if (typeof nameVal !== "string")
{
return alert("name of value: '" + nameVal + "' are not string");
}
for (let i = 0; i < vals.length; i++)
{
if (vals[i] === nameVal)
{
return true;
}
}
if (optValue !== undefined)
{
GM.setValue(nameVal, optValue);
return true;
} else
{
return false;
}
}
async DeleteValuesGM(nameVal)
{
var vals = await GM.listValues();
if (vals.length === 0 || typeof nameVal !== "string")
{
return;
}
switch (nameVal)
{
case "all":
for (let i = 0; i < vals.length; i++)
{
if (vals[i] !== "adm")
{
GM.deleteValue(vals[i]);
}
}
break;
case "old":
for (let i = 0; i < vals.length; i++)
{
if (vals[i] === "debug" || vals[i] === "debugA")
{
GM.deleteValue(vals[i]);
}
}
break;
default:
for (let i = 0; i < vals.length; i++)
{
if (vals[i] === nameVal)
{
GM.deleteValue(nameVal);
}
}
break;
}
}
async UpdateGM(what)
{
var gmVal;
switch (what)
{
case "options":
gmVal = JSON.stringify(options.values);
GM.setValue("pp_options", gmVal);
break;
default:
alert("class:Options.UpdateGM(" + what + "). default switch");
break;
}
}
//async Methods/Functions GM_VALUE
//End
}
let pp = new PinterestPlus();
$(window).on("load", function ()
{
setTimeout(() =>
{
pp.Main();
console.log(pp);
}, 1000);
});