├── README.md ├── WhichFaceIsRealScoreKeeper ├── README.md └── WhichFaceIsRealScoreKeeper.user.js ├── amazonReviewWall ├── README.md ├── amazonReviewWall.user.js ├── amazonReviewWallNewTab.user.js ├── amzn └── images │ ├── amazonReviewWall.gif │ ├── amazonReviewWall.png │ └── amazonReviewWall_small.png ├── githubForkz ├── README.md ├── githubForkz.user.js └── showActivity.js ├── other └── ignmf.js └── pimeyesJS ├── README.md └── pimeyesJS.user.js /README.md: -------------------------------------------------------------------------------- 1 | # usefulUserScripts 2 | pimeyes.js: Mods to make pimeyes.com work better for both premium and free users 3 | amazonReviewWall: Mods to make Amazon show a zoomable review wall 4 | -------------------------------------------------------------------------------- /WhichFaceIsRealScoreKeeper/README.md: -------------------------------------------------------------------------------- 1 | Test your human identification skills! This script keeps a rudimentary score for you on [whichfaceisreal.com](whichfaceisreal.com) since they don't have that built in. 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /WhichFaceIsRealScoreKeeper/WhichFaceIsRealScoreKeeper.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name WhichFaceIsReal Score Keeper 3 | // @namespace Violentmonkey Scripts 4 | // @namespace2 https://github.com/deltabravozulu/usefulUserScripts 5 | // @updateURL https://github.com/deltabravozulu/usefulUserScripts/raw/main/WhichFaceIsRealScoreKeeper/WhichFaceIsRealScoreKeeper.user.js 6 | // @match *://www.whichfaceisreal.com/* 7 | // @grant none 8 | // @version 4.20.69 9 | // @author DeltaBravoZulu 10 | // @description Test your human identification skills! This script keeps score for you on whichfaceisreal.com since they don't have that built in 11 | // @description 2/18/2022, 1:23:53 PM 12 | // @run-at document-idle 13 | // @license PayMe 14 | // ==/UserScript== 15 | 16 | // Make sure page loads before starting 17 | new MutationObserver(check).observe(document, { 18 | childList: true, 19 | subtree: true 20 | }) 21 | 22 | function check (changes, observer) { 23 | if ( 24 | document.querySelector('#bs-example-navbar-collapse-1 > ul > li:nth-child(6)') 25 | ) { 26 | observer.disconnect() 27 | doIt() 28 | } 29 | } 30 | 31 | function doIt () { 32 | let cor = 0 33 | let incor = 0 34 | let correct; let corElement = document.querySelector('html>body>div>div>div>p') 35 | if (corElement != null) { 36 | correct = document.querySelector('html>body>div>div>div>p').textContent.includes('You are correct') 37 | } else { 38 | correct === false 39 | } 40 | let incorrect; let incorElement = document.querySelector('html>body>div>div>div>p') 41 | if (incorElement != null) { 42 | incorrect = document.querySelector('html>body>div>div>div>p').textContent.includes('You are incorrect') 43 | } else { 44 | incorrect === false 45 | } 46 | 47 | function corScore () { 48 | // Get Item from LocalStorage or correctCount === 0 49 | let correctCount = parseInt(localStorage.getItem('correctCount'), 10) || parseInt(0, 10) 50 | 51 | if (typeof correct !== 'undefined') { 52 | if (correct === true) { 53 | cor += 1 54 | } 55 | } 56 | if (cor > 0) { 57 | // Set the score to the users' current points 58 | correctCount = parseInt(correctCount, 10) + parseInt(cor, 10) 59 | // Store the score 60 | localStorage.setItem('correctCount', parseInt(correctCount, 10)) 61 | } 62 | 63 | // Return the high score 64 | return correctCount 65 | } 66 | 67 | function incorScore () { 68 | // Get Item from LocalStorage or incorrectCount === 0 69 | let incorrectCount = parseInt(localStorage.getItem('incorrectCount'), 10) || parseInt(0, 10) 70 | 71 | if (incorrect === true) { incor += 1 } 72 | if (incor > 0) { 73 | // Set the score to the users' current points 74 | incorrectCount = parseInt(incorrectCount, 10) + parseInt(incor, 10) 75 | // Store the score 76 | localStorage.setItem('incorrectCount', parseInt(incorrectCount, 10)) 77 | } 78 | 79 | // Return the high score 80 | return incorrectCount 81 | } 82 | 83 | function getScore () { 84 | let currentCorScore = parseInt(localStorage.getItem('correctCount'), 10) 85 | let currentInCorScore = parseInt(localStorage.getItem('incorrectCount'), 10) 86 | 87 | function nukeScore () { 88 | localStorage.setItem('correctCount', 0) 89 | localStorage.setItem('incorrectCount', 0) 90 | document.querySelector('#inject').remove() 91 | getScore() 92 | } 93 | console.log('Correct: ' + currentCorScore) 94 | console.log('Incorrect: ' + currentInCorScore) 95 | htmlInject = '
' 96 | document.querySelector('body > nav').insertAdjacentHTML('afterend', htmlInject) 97 | scoreInject = '
  Correct: ' + currentCorScore + '      Incorrect: ' + currentInCorScore + '
' 98 | document.querySelector('#inject').insertAdjacentHTML('afterbegin', scoreInject) 99 | buttonInject = '
' 100 | document.querySelector('#score').insertAdjacentHTML('afterend', buttonInject) 101 | document.getElementById('resetter').addEventListener('click', nukeScore) 102 | } 103 | corScore() 104 | incorScore() 105 | getScore() 106 | } 107 | -------------------------------------------------------------------------------- /amazonReviewWall/README.md: -------------------------------------------------------------------------------- 1 |

amazonReviewWall

2 |
Mods to make Amazon show an image wall of user reviews
3 |
4 | 11 | 12 |
13 |

This is a UserScript written for Violent Monkey but should work on other UserScript extensions as well

14 |
15 |

Installation:

16 | Open amazonReviewWall.user.js 17 | 18 | 19 | -------------------------------------------------------------------------------- /amazonReviewWall/amazonReviewWall.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name amazonReviewWall 3 | // @namespace https://github.com/deltabravozulu/usefulUserScripts 4 | // @version 420.69.2022-05-12T14:28:42 5 | // @author DeltaBravoZulu 6 | // @description View Amazon review images in a zoomable wall 7 | // @homepage https://github.com/deltabravozulu/usefulUserScripts/tree/main/amazonReviewWall 8 | // @icon https://raw.githubusercontent.com/deltabravozulu/usefulUserScripts/main/amazonReviewWall/images/amazonReviewWall_small.png 9 | // @icon64 https://raw.githubusercontent.com/deltabravozulu/usefulUserScripts/main/amazonReviewWall/images/amazonReviewWall_small.png 10 | // @updateURL https://raw.githubusercontent.com/deltabravozulu/usefulUserScripts/main/amazonReviewWall/amazonReviewWall.user.js 11 | // @downloadURL https://raw.githubusercontent.com/deltabravozulu/usefulUserScripts/main/amazonReviewWall/amazonReviewWall.user.js 12 | // @supportURL https://github.com/deltabravozulu/usefulUserScripts 13 | // @include /^https?:\/\/(www|smile)\.amazon\.(cn|in|co\.jp|sg|ae|fr|de|it|nl|es|co\.uk|ca|com(\.(mx|au|br|tr))?)\/.*(dp|gp\/(product|video)|exec\/obidos\/ASIN|o\/ASIN)\/.*$/ 14 | // @grant GM_setValue 15 | // @grant GM_getValue 16 | // @grant window.close 17 | // @grant window.focus 18 | // @run-at document-idle 19 | // @license PayMe 20 | // ==/UserScript== 21 | /////////////////////////////////////// 22 | // Amazon Review Photowall // 23 | /////////////////////////////////////// 24 | /* 25 | ** Makes a zoomable photo wall from Amazon review pictures 26 | */ 27 | async function theStuff() { 28 | function sleep(ms) { 29 | return new Promise((resolve) => setTimeout(resolve, ms)); 30 | } 31 | function appendHTML() { 32 | var wrapper = document.createElement("body"); 33 | wrapper.innerHTML = 34 | '\ 35 | \ 89 |
\ 90 | '; 91 | document.appendChild(wrapper); 92 | } 93 | await sleep(1000); 94 | //https://stackoverflow.com/a/58316317/8398127 95 | function getChunks(selector, strStart, strEnd) { 96 | const html = document.querySelector(selector).innerHTML; 97 | const start = html.indexOf(strStart); 98 | const end = html.indexOf(strEnd, start); 99 | if (start == -1 || end == -1) return; 100 | return { 101 | before: html.substr(0, start), 102 | match: html.substr(start, end - start + strEnd.length), 103 | after: html.substr(end + strEnd.length, html.length - end), 104 | }; 105 | } 106 | let chunkSelector = "#reviews-image-gallery-container > script"; 107 | let chunkStart = "data, "; 108 | let chunkEnd = '");'; 109 | chunks = getChunks(chunkSelector, chunkStart, chunkEnd).match; 110 | dataAndCSRF = chunks 111 | .replaceAll(");", "") 112 | .replaceAll('"', "") 113 | .replaceAll(" ", ""); 114 | dataAndCSRFArray = dataAndCSRF.split(","); 115 | data = dataAndCSRFArray[1]; 116 | firstReviewIds = dataAndCSRFArray[3]; 117 | asin = data; 118 | csrfToken = firstReviewIds; 119 | let text = ""; 120 | let date = new Date().toISOString(); 121 | function AppendToLocalStorage(name, value) { 122 | let n = 0; 123 | while (localStorage.getItem(name + "-" + n)) { 124 | n++; 125 | } 126 | localStorage.setItem(name + "-" + n, value); //add item at first available index number 127 | } 128 | function GetLocalStorage(name) { 129 | let n = 0; 130 | let data = []; 131 | while (localStorage.getItem(name + "-" + n)) { 132 | data.push(localStorage.getItem(name + "-" + n++)); 133 | } 134 | return data; 135 | } 136 | function AppendToGMStorage(name, value) { 137 | let n = 0; 138 | while (GM_getValue(name + "-" + n, "")) { 139 | n++; 140 | } 141 | GM_setValue(name + "-" + n, value); //add item at first available index number 142 | } 143 | function GetGMStorage(name) { 144 | let n = 0; 145 | let data = []; 146 | while (GM_getValue(name + "-" + n, "")) { 147 | data.push(GM_getValue(name + "-" + n++)); 148 | } 149 | return data; 150 | } 151 | //https://www.amazon.com/hz/reviews-render/get-reviews-with-media?mediaType=image&asin=B08DKK2KD1&csrfToken=guMT%2B0nYuIuyIIE6DbwfM0%2BcGnpEsbBr8SAKSRIAAAABAAAAAGJ5vEhyYXcAAAAA%2B4kUEk%2F7iMGR3xPcX6iU 152 | function loadReviews() { 153 | url = 154 | "https://www.amazon.com/hz/reviews-render/get-reviews-with-media?mediaType=image&asin=" + 155 | asin + 156 | "&csrfToken=" + 157 | csrfToken; 158 | function getJSON(url) { 159 | var resp; 160 | var xmlHttp; 161 | resp = ""; 162 | xmlHttp = new XMLHttpRequest(); 163 | if (xmlHttp != null) { 164 | xmlHttp.open("GET", url, false); 165 | xmlHttp.send(null); 166 | resp = xmlHttp.responseText; 167 | } 168 | return resp; 169 | } 170 | jsonGot = getJSON(url); 171 | jsonParsed = JSON.parse(jsonGot); 172 | //need to keep doing this until all pages are hit 173 | csrfToken = jsonParsed.csrfToken; 174 | reviews = jsonParsed.reviewsWithMediaList; 175 | reviewKeys = Object.keys(reviews); 176 | reviewCount = reviewKeys.length; 177 | for (var r = 0; r < reviewCount; r++) { 178 | reviewKey = reviewKeys[r]; 179 | review = reviews[reviewKey]; 180 | //console.log(review) 181 | reviewId = review.reviewId; 182 | reviewUrl = 183 | "https://www.amazon.com/gp/customer-reviews/" + reviewId; 184 | profileUrl = "https://www.amazon.com" + review.customerProfileLink; 185 | AppendToGMStorage(asin, profileUrl); 186 | AppendToLocalStorage(asin, profileUrl); 187 | for (var j = 0; j < review.images.length; j++) { 188 | imgUrl = review.images[j].source; 189 | text += 190 | ''; 197 | console.log( 198 | "imgUrl: " + 199 | imgUrl + 200 | ", reviewUrl: " + 201 | reviewUrl + 202 | ", profileUrl: " + 203 | profileUrl 204 | ); 205 | //console.log(csrfToken) 206 | } 207 | } 208 | } 209 | loadReviews(); 210 | await sleep(3000); 211 | var newDoc = document.open("text/html", "replace"); 212 | appendHTML(); 213 | await sleep(1000); 214 | document.getElementById("zoomwall").innerHTML = text; 215 | await sleep(1000); 216 | var zoomwall = { 217 | create: function (blocks, enableKeys) { 218 | zoomwall.resize(blocks.children); 219 | blocks.classList.remove("loading"); 220 | // shrink blocks if an empty space is clicked 221 | blocks.addEventListener("click", function () { 222 | if (this.children && this.children.length > 0) { 223 | zoomwall.shrink(this.children[0]); 224 | } 225 | }); 226 | // add click listeners to blocks 227 | for (var i = 0; i < blocks.children.length; i++) { 228 | blocks.children[i].addEventListener("click", zoomwall.animate); 229 | } 230 | // add key down listener 231 | if (enableKeys) { 232 | var keyPager = function (event) { 233 | which = event.which; 234 | keyCode = event.keyCode; 235 | shiftKey = event.shiftKey; 236 | altKey = event.altKey; 237 | ctrlKey = event.ctrlKey; 238 | metaKey = event.metaKey; 239 | key = event.key; 240 | defaultPrevented = event.defaultPrevented; 241 | //[prevent key codes from working when shift,alt,ctrl,cmd,windows,super,etc. keys are working ] 242 | if ( 243 | defaultPrevented || 244 | shiftKey || 245 | altKey || 246 | ctrlKey || 247 | metaKey 248 | ) { 249 | console.log(key); 250 | return; 251 | } 252 | //[ESC] = zoom out 253 | else if (keyCode === 27) { 254 | console.log(key); 255 | if (blocks.children && blocks.children.length > 0) { 256 | zoomwall.shrink(blocks.children[0]); 257 | } 258 | event.preventDefault(); 259 | } 260 | //[⬅] = previous 261 | else if (keyCode === 37) { 262 | console.log(key); 263 | zoomwall.page(blocks, false); 264 | event.preventDefault(); 265 | } 266 | //[➡] = next 267 | else if (keyCode === 39) { 268 | console.log(key); 269 | zoomwall.page(blocks, true); 270 | event.preventDefault(); 271 | } 272 | //[space]||[⬆]||[r] = open review 273 | else if ( 274 | keyCode === 32 || 275 | keyCode === 38 || 276 | keyCode === 82 277 | ) { 278 | console.log(key); 279 | zoomwall.reviewUrl(blocks); 280 | event.preventDefault(); 281 | } 282 | //[⬇]||[p] = open profile 283 | else if (keyCode === 40 || keyCode === 80) { 284 | console.log(key); 285 | zoomwall.profileUrl(blocks); 286 | event.preventDefault(); 287 | } else { 288 | console.log(key); 289 | return; 290 | } 291 | }; 292 | document.addEventListener("keydown", keyPager); 293 | } 294 | }, 295 | resizeRow: function (row, width) { 296 | if (row && row.length > 1) { 297 | for (var i in row) { 298 | row[i].style.width = 299 | (parseInt(window.getComputedStyle(row[i]).width, 10) / 300 | width) * 301 | 100 + 302 | "%"; 303 | row[i].style.height = "auto"; 304 | } 305 | } 306 | }, 307 | calcRowWidth: function (row) { 308 | var width = 0; 309 | for (var i in row) { 310 | width += parseInt(window.getComputedStyle(row[i]).width, 10); 311 | } 312 | return width; 313 | }, 314 | resize: function (blocks) { 315 | var row = []; 316 | var top = -1; 317 | for (var c = 0; c < blocks.length; c++) { 318 | var block = blocks[c]; 319 | if (block) { 320 | if (top == -1) { 321 | top = block.offsetTop; 322 | } else if (block.offsetTop != top) { 323 | zoomwall.resizeRow(row, zoomwall.calcRowWidth(row)); 324 | row = []; 325 | top = block.offsetTop; 326 | } 327 | row.push(block); 328 | } 329 | } 330 | zoomwall.resizeRow(row, zoomwall.calcRowWidth(row)); 331 | }, 332 | reset: function (block) { 333 | block.style.transform = "translate(0, 0) scale(1)"; 334 | block.style.webkitTransform = "translate(0, 0) scale(1)"; 335 | block.classList.remove("active"); 336 | }, 337 | shrink: function (block) { 338 | block.parentNode.classList.remove("lightbox"); 339 | // reset all blocks 340 | zoomwall.reset(block); 341 | var prev = block.previousElementSibling; 342 | while (prev) { 343 | zoomwall.reset(prev); 344 | prev = prev.previousElementSibling; 345 | } 346 | var next = block.nextElementSibling; 347 | while (next) { 348 | zoomwall.reset(next); 349 | next = next.nextElementSibling; 350 | } 351 | // swap images 352 | if (block.dataset.lowres) { 353 | block.src = block.dataset.lowres; 354 | } 355 | }, 356 | expand: function (block) { 357 | block.classList.add("active"); 358 | block.parentNode.classList.add("lightbox"); 359 | // parent dimensions 360 | var parentStyle = window.getComputedStyle(block.parentNode); 361 | var parentWidth = parseInt(parentStyle.width, 10); 362 | var parentHeight = parseInt(parentStyle.height, 10); 363 | var parentTop = block.parentNode.getBoundingClientRect().top; 364 | // block dimensions 365 | var blockStyle = window.getComputedStyle(block); 366 | var blockWidth = parseInt(blockStyle.width, 10); 367 | var blockHeight = parseInt(blockStyle.height, 10); 368 | // determine maximum height 369 | var targetHeight = window.innerHeight; 370 | if (parentHeight < window.innerHeight) { 371 | targetHeight = parentHeight; 372 | } else if (parentTop > 0) { 373 | targetHeight -= parentTop; 374 | } 375 | // swap images 376 | if (block.dataset.highres) { 377 | if ( 378 | block.src != block.dataset.highres && 379 | block.dataset.lowres === undefined 380 | ) { 381 | block.dataset.lowres = block.src; 382 | } 383 | block.src = block.dataset.highres; 384 | } 385 | // determine what blocks are on this row 386 | var row = []; 387 | row.push(block); 388 | var next = block.nextElementSibling; 389 | while (next && next.offsetTop == block.offsetTop) { 390 | row.push(next); 391 | next = next.nextElementSibling; 392 | } 393 | var prev = block.previousElementSibling; 394 | while (prev && prev.offsetTop == block.offsetTop) { 395 | row.unshift(prev); 396 | prev = prev.previousElementSibling; 397 | } 398 | // calculate scale 399 | var scale = targetHeight / blockHeight; 400 | if (blockWidth * scale > parentWidth) { 401 | scale = parentWidth / blockWidth; 402 | } 403 | // determine offset 404 | var offsetY = 405 | parentTop - block.parentNode.offsetTop + block.offsetTop; 406 | if (offsetY > 0) { 407 | if (parentHeight < window.innerHeight) { 408 | offsetY -= targetHeight / 2 - (blockHeight * scale) / 2; 409 | } 410 | if (parentTop > 0) { 411 | offsetY -= parentTop; 412 | } 413 | } 414 | var leftOffsetX = 0; // shift in current row 415 | for (var i = 0; i < row.length && row[i] != block; i++) { 416 | leftOffsetX += 417 | parseInt(window.getComputedStyle(row[i]).width, 10) * scale; 418 | } 419 | leftOffsetX = 420 | parentWidth / 2 - (blockWidth * scale) / 2 - leftOffsetX; 421 | var rightOffsetX = 0; // shift in current row 422 | for (var i = row.length - 1; i >= 0 && row[i] != block; i--) { 423 | rightOffsetX += 424 | parseInt(window.getComputedStyle(row[i]).width, 10) * scale; 425 | } 426 | rightOffsetX = 427 | parentWidth / 2 - (blockWidth * scale) / 2 - rightOffsetX; 428 | // transform current row 429 | var itemOffset = 0; // offset due to scaling of previous items 430 | var prevWidth = 0; 431 | for (var i = 0; i < row.length; i++) { 432 | itemOffset += prevWidth * scale - prevWidth; 433 | prevWidth = parseInt(window.getComputedStyle(row[i]).width, 10); 434 | var percentageOffsetX = 435 | ((itemOffset + leftOffsetX) / prevWidth) * 100; 436 | var percentageOffsetY = 437 | (-offsetY / 438 | parseInt(window.getComputedStyle(row[i]).height, 10)) * 439 | 100; 440 | row[i].style.transformOrigin = "0% 0%"; 441 | row[i].style.webkitTransformOrigin = "0% 0%"; 442 | row[i].style.transform = 443 | "translate(" + 444 | percentageOffsetX.toFixed(8) + 445 | "%, " + 446 | percentageOffsetY.toFixed(8) + 447 | "%) scale(" + 448 | scale.toFixed(8) + 449 | ")"; 450 | row[i].style.webkitTransform = 451 | "translate(" + 452 | percentageOffsetX.toFixed(8) + 453 | "%, " + 454 | percentageOffsetY.toFixed(8) + 455 | "%) scale(" + 456 | scale.toFixed(8) + 457 | ")"; 458 | } 459 | // transform items after 460 | var nextOffsetY = blockHeight * (scale - 1) - offsetY; 461 | var prevHeight; 462 | itemOffset = 0; // offset due to scaling of previous items 463 | prevWidth = 0; 464 | var next = row[row.length - 1].nextElementSibling; 465 | var nextRowTop = -1; 466 | while (next) { 467 | var curTop = next.offsetTop; 468 | if (curTop == nextRowTop) { 469 | itemOffset += prevWidth * scale - prevWidth; 470 | } else { 471 | if (nextRowTop != -1) { 472 | itemOffset = 0; 473 | nextOffsetY += prevHeight * (scale - 1); 474 | } 475 | nextRowTop = curTop; 476 | } 477 | prevWidth = parseInt(window.getComputedStyle(next).width, 10); 478 | prevHeight = parseInt(window.getComputedStyle(next).height, 10); 479 | var percentageOffsetX = 480 | ((itemOffset + leftOffsetX) / prevWidth) * 100; 481 | var percentageOffsetY = (nextOffsetY / prevHeight) * 100; 482 | next.style.transformOrigin = "0% 0%"; 483 | next.style.webkitTransformOrigin = "0% 0%"; 484 | next.style.transform = 485 | "translate(" + 486 | percentageOffsetX.toFixed(8) + 487 | "%, " + 488 | percentageOffsetY.toFixed(8) + 489 | "%) scale(" + 490 | scale.toFixed(8) + 491 | ")"; 492 | next.style.webkitTransform = 493 | "translate(" + 494 | percentageOffsetX.toFixed(8) + 495 | "%, " + 496 | percentageOffsetY.toFixed(8) + 497 | "%) scale(" + 498 | scale.toFixed(8) + 499 | ")"; 500 | next = next.nextElementSibling; 501 | } 502 | // transform items before 503 | var prevOffsetY = -offsetY; 504 | itemOffset = 0; // offset due to scaling of previous items 505 | prevWidth = 0; 506 | var prev = row[0].previousElementSibling; 507 | var prevRowTop = -1; 508 | while (prev) { 509 | var curTop = prev.offsetTop; 510 | if (curTop == prevRowTop) { 511 | itemOffset -= prevWidth * scale - prevWidth; 512 | } else { 513 | itemOffset = 0; 514 | prevOffsetY -= 515 | parseInt(window.getComputedStyle(prev).height, 10) * 516 | (scale - 1); 517 | prevRowTop = curTop; 518 | } 519 | prevWidth = parseInt(window.getComputedStyle(prev).width, 10); 520 | var percentageOffsetX = 521 | ((itemOffset - rightOffsetX) / prevWidth) * 100; 522 | var percentageOffsetY = 523 | (prevOffsetY / 524 | parseInt(window.getComputedStyle(prev).height, 10)) * 525 | 100; 526 | prev.style.transformOrigin = "100% 0%"; 527 | prev.style.webkitTransformOrigin = "100% 0%"; 528 | prev.style.transform = 529 | "translate(" + 530 | percentageOffsetX.toFixed(8) + 531 | "%, " + 532 | percentageOffsetY.toFixed(8) + 533 | "%) scale(" + 534 | scale.toFixed(8) + 535 | ")"; 536 | prev.style.webkitTransform = 537 | "translate(" + 538 | percentageOffsetX.toFixed(8) + 539 | "%, " + 540 | percentageOffsetY.toFixed(8) + 541 | "%) scale(" + 542 | scale.toFixed(8) + 543 | ")"; 544 | prev = prev.previousElementSibling; 545 | } 546 | }, 547 | animate: function (e) { 548 | if (this.classList.contains("active")) { 549 | zoomwall.shrink(this); 550 | } else { 551 | var actives = this.parentNode.getElementsByClassName("active"); 552 | for (var i = 0; i < actives.length; i++) { 553 | actives[i].classList.remove("active"); 554 | } 555 | zoomwall.expand(this); 556 | } 557 | e.stopPropagation(); 558 | }, 559 | reviewUrl: function (blocks) { 560 | var actives = blocks.getElementsByClassName("active"); 561 | if (actives && actives.length > 0) { 562 | var current = actives[0]; 563 | } 564 | window.open(current.attributes.reviewurl.value, "_blank").blur(); 565 | self.focus(); 566 | }, 567 | profileUrl: function (blocks) { 568 | var actives = blocks.getElementsByClassName("active"); 569 | if (actives && actives.length > 0) { 570 | var current = actives[0]; 571 | } 572 | window.open(current.attributes.profileurl.value, "_blank").blur(); 573 | self.focus(); 574 | }, 575 | page: function (blocks, isNext) { 576 | var actives = blocks.getElementsByClassName("active"); 577 | if (actives && actives.length > 0) { 578 | var current = actives[0]; 579 | var next; 580 | if (isNext) { 581 | next = current.nextElementSibling; 582 | } else { 583 | next = current.previousElementSibling; 584 | } 585 | if (next) { 586 | current.classList.remove("active"); 587 | // swap images 588 | if (current.dataset.lowres) { 589 | current.src = current.dataset.lowres; 590 | } 591 | zoomwall.expand(next); 592 | } 593 | } 594 | }, 595 | }; 596 | await sleep(1000); 597 | zoomwall.create(document.getElementById("zoomwall"), true); 598 | await sleep(1000); 599 | newDoc.close(); 600 | } 601 | /////////////////////////////////////// 602 | // Button Injections // 603 | /////////////////////////////////////// 604 | /* 605 | ** Adds button to process start 606 | */ 607 | function addButts() { 608 | console.log("Adding Button"); 609 | var oldButtons = document.querySelector("#productTitle"); 610 | var newButtons = oldButtons.parentElement; 611 | var iconHtml = 612 | ''; 613 | newButtons.insertAdjacentHTML("beforeend", iconHtml); 614 | document 615 | .getElementById("ImageWallButton") 616 | .addEventListener("click", theStuff); 617 | console.log("Added Button"); 618 | } 619 | addButts(); 620 | -------------------------------------------------------------------------------- /amazonReviewWall/amazonReviewWallNewTab.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name amazonReviewWallNewTab 3 | // @namespace https://github.com/deltabravozulu/usefulUserScripts 4 | // @version 420.69.2022-05-12T15:13:40 5 | // @author DeltaBravoZulu 6 | // @description View Amazon review images in a zoomable wall 7 | // @homepage https://github.com/deltabravozulu/usefulUserScripts/tree/main/amazonReviewWall 8 | // @icon https://raw.githubusercontent.com/deltabravozulu/usefulUserScripts/main/amazonReviewWall/images/amazonReviewWall_small.png 9 | // @icon64 https://raw.githubusercontent.com/deltabravozulu/usefulUserScripts/main/amazonReviewWall/images/amazonReviewWall_small.png 10 | // @updateURL https://raw.githubusercontent.com/deltabravozulu/usefulUserScripts/main/amazonReviewWall/amazonReviewWallNewTab.user.js 11 | // @downloadURL https://raw.githubusercontent.com/deltabravozulu/usefulUserScripts/main/amazonReviewWall/amazonReviewWallNewTab.user.js 12 | // @supportURL https://github.com/deltabravozulu/usefulUserScripts 13 | // @include /^https?:\/\/(www|smile)\.amazon\.(cn|in|co\.jp|sg|ae|fr|de|it|nl|es|co\.uk|ca|com(\.(mx|au|br|tr))?)\/.*(dp|gp\/(product|video)|exec\/obidos\/ASIN|o\/ASIN)\/.*$/ 14 | // @grant GM_setValue 15 | // @grant GM_getValue 16 | // @grant window.close 17 | // @grant window.focus 18 | // @run-at document-idle 19 | // @license PayMe 20 | // ==/UserScript== 21 | /////////////////////////////////////// 22 | // Amazon Review Photowall // 23 | /////////////////////////////////////// 24 | /* 25 | ** Makes a zoomable photo wall from Amazon review pictures 26 | */ 27 | async function theStuff() { 28 | function sleep(ms) { 29 | return new Promise((resolve) => setTimeout(resolve, ms)); 30 | } 31 | function appendHTML() { 32 | var wrapper = newWindow.document.createElement("body"); 33 | wrapper.innerHTML = 34 | '\ 35 | \ 89 |
\ 90 | '; 91 | newWindow.document.appendChild(wrapper); 92 | } 93 | await sleep(1000); 94 | //https://stackoverflow.com/a/58316317/8398127 95 | function getChunks(selector, strStart, strEnd) { 96 | const html = document.querySelector(selector).innerHTML; 97 | const start = html.indexOf(strStart); 98 | const end = html.indexOf(strEnd, start); 99 | if (start == -1 || end == -1) return; 100 | return { 101 | before: html.substr(0, start), 102 | match: html.substr(start, end - start + strEnd.length), 103 | after: html.substr(end + strEnd.length, html.length - end), 104 | }; 105 | } 106 | let chunkSelector = "#reviews-image-gallery-container > script"; 107 | let chunkStart = "data, "; 108 | let chunkEnd = '");'; 109 | chunks = getChunks(chunkSelector, chunkStart, chunkEnd).match; 110 | dataAndCSRF = chunks 111 | .replaceAll(");", "") 112 | .replaceAll('"', "") 113 | .replaceAll(" ", ""); 114 | dataAndCSRFArray = dataAndCSRF.split(","); 115 | data = dataAndCSRFArray[1]; 116 | firstReviewIds = dataAndCSRFArray[3]; 117 | asin = data; 118 | csrfToken = firstReviewIds; 119 | let text = ""; 120 | let date = new Date().toISOString(); 121 | function AppendToLocalStorage(name, value) { 122 | let n = 0; 123 | while (localStorage.getItem(name + "-" + n)) { 124 | n++; 125 | } 126 | localStorage.setItem(name + "-" + n, value); //add item at first available index number 127 | } 128 | function GetLocalStorage(name) { 129 | let n = 0; 130 | let data = []; 131 | while (localStorage.getItem(name + "-" + n)) { 132 | data.push(localStorage.getItem(name + "-" + n++)); 133 | } 134 | return data; 135 | } 136 | function AppendToGMStorage(name, value) { 137 | let n = 0; 138 | while (GM_getValue(name + "-" + n, "")) { 139 | n++; 140 | } 141 | GM_setValue(name + "-" + n, value); //add item at first available index number 142 | } 143 | function GetGMStorage(name) { 144 | let n = 0; 145 | let data = []; 146 | while (GM_getValue(name + "-" + n, "")) { 147 | data.push(GM_getValue(name + "-" + n++)); 148 | } 149 | return data; 150 | } 151 | //https://www.amazon.com/hz/reviews-render/get-reviews-with-media?mediaType=image&asin=B08DKK2KD1&csrfToken=guMT%2B0nYuIuyIIE6DbwfM0%2BcGnpEsbBr8SAKSRIAAAABAAAAAGJ5vEhyYXcAAAAA%2B4kUEk%2F7iMGR3xPcX6iU 152 | function loadReviews() { 153 | url = 154 | "https://www.amazon.com/hz/reviews-render/get-reviews-with-media?mediaType=image&asin=" + 155 | asin + 156 | "&csrfToken=" + 157 | csrfToken; 158 | function getJSON(url) { 159 | var resp; 160 | var xmlHttp; 161 | resp = ""; 162 | xmlHttp = new XMLHttpRequest(); 163 | if (xmlHttp != null) { 164 | xmlHttp.open("GET", url, false); 165 | xmlHttp.send(null); 166 | resp = xmlHttp.responseText; 167 | } 168 | return resp; 169 | } 170 | jsonGot = getJSON(url); 171 | jsonParsed = JSON.parse(jsonGot); 172 | //need to keep doing this until all pages are hit 173 | csrfToken = jsonParsed.csrfToken; 174 | reviews = jsonParsed.reviewsWithMediaList; 175 | reviewKeys = Object.keys(reviews); 176 | reviewCount = reviewKeys.length; 177 | for (var r = 0; r < reviewCount; r++) { 178 | reviewKey = reviewKeys[r]; 179 | review = reviews[reviewKey]; 180 | //console.log(review) 181 | reviewId = review.reviewId; 182 | reviewUrl = 183 | "https://www.amazon.com/gp/customer-reviews/" + reviewId; 184 | profileUrl = "https://www.amazon.com" + review.customerProfileLink; 185 | AppendToGMStorage(asin, profileUrl); 186 | AppendToLocalStorage(asin, profileUrl); 187 | for (var j = 0; j < review.images.length; j++) { 188 | imgUrl = review.images[j].source; 189 | text += 190 | ''; 197 | console.log( 198 | "imgUrl: " + 199 | imgUrl + 200 | ", reviewUrl: " + 201 | reviewUrl + 202 | ", profileUrl: " + 203 | profileUrl 204 | ); 205 | //console.log(csrfToken) 206 | } 207 | } 208 | } 209 | loadReviews(); 210 | await sleep(3000); 211 | var newWindow = window.open(); 212 | newWindow.document.body.innerHTML = 'howdy'; 213 | var newDoc = newWindow.document.open("text/html", "replace"); 214 | appendHTML(); 215 | await sleep(1000); 216 | newWindow.document.getElementById("zoomwall").innerHTML = text; 217 | await sleep(1000); 218 | var zoomwall = { 219 | create: function (blocks, enableKeys) { 220 | zoomwall.resize(blocks.children); 221 | blocks.classList.remove("loading"); 222 | // shrink blocks if an empty space is clicked 223 | blocks.addEventListener("click", function () { 224 | if (this.children && this.children.length > 0) { 225 | zoomwall.shrink(this.children[0]); 226 | } 227 | }); 228 | // add click listeners to blocks 229 | for (var i = 0; i < blocks.children.length; i++) { 230 | blocks.children[i].addEventListener("click", zoomwall.animate); 231 | } 232 | // add key down listener 233 | if (enableKeys) { 234 | var keyPager = function (event) { 235 | which = event.which; 236 | keyCode = event.keyCode; 237 | shiftKey = event.shiftKey; 238 | altKey = event.altKey; 239 | ctrlKey = event.ctrlKey; 240 | metaKey = event.metaKey; 241 | key = event.key; 242 | defaultPrevented = event.defaultPrevented; 243 | //[prevent key codes from working when shift,alt,ctrl,cmd,windows,super,etc. keys are working ] 244 | if ( 245 | defaultPrevented || 246 | shiftKey || 247 | altKey || 248 | ctrlKey || 249 | metaKey 250 | ) { 251 | console.log(key); 252 | return; 253 | } 254 | //[ESC] = zoom out 255 | else if (keyCode === 27) { 256 | console.log(key); 257 | if (blocks.children && blocks.children.length > 0) { 258 | zoomwall.shrink(blocks.children[0]); 259 | } 260 | event.preventDefault(); 261 | } 262 | //[⬅] = previous 263 | else if (keyCode === 37) { 264 | console.log(key); 265 | zoomwall.page(blocks, false); 266 | event.preventDefault(); 267 | } 268 | //[➡] = next 269 | else if (keyCode === 39) { 270 | console.log(key); 271 | zoomwall.page(blocks, true); 272 | event.preventDefault(); 273 | } 274 | //[space]||[⬆]||[r] = open review 275 | else if ( 276 | keyCode === 32 || 277 | keyCode === 38 || 278 | keyCode === 82 279 | ) { 280 | console.log(key); 281 | zoomwall.reviewUrl(blocks); 282 | event.preventDefault(); 283 | } 284 | //[⬇]||[p] = open profile 285 | else if (keyCode === 40 || keyCode === 80) { 286 | console.log(key); 287 | zoomwall.profileUrl(blocks); 288 | event.preventDefault(); 289 | } else { 290 | console.log(key); 291 | return; 292 | } 293 | }; 294 | newWindow.document.addEventListener("keydown", keyPager); 295 | } 296 | }, 297 | resizeRow: function (row, width) { 298 | if (row && row.length > 1) { 299 | for (var i in row) { 300 | row[i].style.width = 301 | (parseInt(window.getComputedStyle(row[i]).width, 10) / 302 | width) * 303 | 100 + 304 | "%"; 305 | row[i].style.height = "auto"; 306 | } 307 | } 308 | }, 309 | calcRowWidth: function (row) { 310 | var width = 0; 311 | for (var i in row) { 312 | width += parseInt(window.getComputedStyle(row[i]).width, 10); 313 | } 314 | return width; 315 | }, 316 | resize: function (blocks) { 317 | var row = []; 318 | var top = -1; 319 | for (var c = 0; c < blocks.length; c++) { 320 | var block = blocks[c]; 321 | if (block) { 322 | if (top == -1) { 323 | top = block.offsetTop; 324 | } else if (block.offsetTop != top) { 325 | zoomwall.resizeRow(row, zoomwall.calcRowWidth(row)); 326 | row = []; 327 | top = block.offsetTop; 328 | } 329 | row.push(block); 330 | } 331 | } 332 | zoomwall.resizeRow(row, zoomwall.calcRowWidth(row)); 333 | }, 334 | reset: function (block) { 335 | block.style.transform = "translate(0, 0) scale(1)"; 336 | block.style.webkitTransform = "translate(0, 0) scale(1)"; 337 | block.classList.remove("active"); 338 | }, 339 | shrink: function (block) { 340 | block.parentNode.classList.remove("lightbox"); 341 | // reset all blocks 342 | zoomwall.reset(block); 343 | var prev = block.previousElementSibling; 344 | while (prev) { 345 | zoomwall.reset(prev); 346 | prev = prev.previousElementSibling; 347 | } 348 | var next = block.nextElementSibling; 349 | while (next) { 350 | zoomwall.reset(next); 351 | next = next.nextElementSibling; 352 | } 353 | // swap images 354 | if (block.dataset.lowres) { 355 | block.src = block.dataset.lowres; 356 | } 357 | }, 358 | expand: function (block) { 359 | block.classList.add("active"); 360 | block.parentNode.classList.add("lightbox"); 361 | // parent dimensions 362 | var parentStyle = newWindow.getComputedStyle(block.parentNode); 363 | var parentWidth = parseInt(parentStyle.width, 10); 364 | var parentHeight = parseInt(parentStyle.height, 10); 365 | var parentTop = block.parentNode.getBoundingClientRect().top; 366 | // block dimensions 367 | var blockStyle = newWindow.getComputedStyle(block); 368 | var blockWidth = parseInt(blockStyle.width, 10); 369 | var blockHeight = parseInt(blockStyle.height, 10); 370 | // determine maximum height 371 | var targetHeight = newWindow.innerHeight; 372 | if (parentHeight < newWindow.innerHeight) { 373 | targetHeight = parentHeight; 374 | } else if (parentTop > 0) { 375 | targetHeight -= parentTop; 376 | } 377 | // swap images 378 | if (block.dataset.highres) { 379 | if ( 380 | block.src != block.dataset.highres && 381 | block.dataset.lowres === undefined 382 | ) { 383 | block.dataset.lowres = block.src; 384 | } 385 | block.src = block.dataset.highres; 386 | } 387 | // determine what blocks are on this row 388 | var row = []; 389 | row.push(block); 390 | var next = block.nextElementSibling; 391 | while (next && next.offsetTop == block.offsetTop) { 392 | row.push(next); 393 | next = next.nextElementSibling; 394 | } 395 | var prev = block.previousElementSibling; 396 | while (prev && prev.offsetTop == block.offsetTop) { 397 | row.unshift(prev); 398 | prev = prev.previousElementSibling; 399 | } 400 | // calculate scale 401 | var scale = targetHeight / blockHeight; 402 | if (blockWidth * scale > parentWidth) { 403 | scale = parentWidth / blockWidth; 404 | } 405 | // determine offset 406 | var offsetY = 407 | parentTop - block.parentNode.offsetTop + block.offsetTop; 408 | if (offsetY > 0) { 409 | if (parentHeight < newWindow.innerHeight) { 410 | offsetY -= targetHeight / 2 - (blockHeight * scale) / 2; 411 | } 412 | if (parentTop > 0) { 413 | offsetY -= parentTop; 414 | } 415 | } 416 | var leftOffsetX = 0; // shift in current row 417 | for (var i = 0; i < row.length && row[i] != block; i++) { 418 | leftOffsetX += 419 | parseInt(window.getComputedStyle(row[i]).width, 10) * scale; 420 | } 421 | leftOffsetX = 422 | parentWidth / 2 - (blockWidth * scale) / 2 - leftOffsetX; 423 | var rightOffsetX = 0; // shift in current row 424 | for (var i = row.length - 1; i >= 0 && row[i] != block; i--) { 425 | rightOffsetX += 426 | parseInt(window.getComputedStyle(row[i]).width, 10) * scale; 427 | } 428 | rightOffsetX = 429 | parentWidth / 2 - (blockWidth * scale) / 2 - rightOffsetX; 430 | // transform current row 431 | var itemOffset = 0; // offset due to scaling of previous items 432 | var prevWidth = 0; 433 | for (var i = 0; i < row.length; i++) { 434 | itemOffset += prevWidth * scale - prevWidth; 435 | prevWidth = parseInt(window.getComputedStyle(row[i]).width, 10); 436 | var percentageOffsetX = 437 | ((itemOffset + leftOffsetX) / prevWidth) * 100; 438 | var percentageOffsetY = 439 | (-offsetY / 440 | parseInt(window.getComputedStyle(row[i]).height, 10)) * 441 | 100; 442 | row[i].style.transformOrigin = "0% 0%"; 443 | row[i].style.webkitTransformOrigin = "0% 0%"; 444 | row[i].style.transform = 445 | "translate(" + 446 | percentageOffsetX.toFixed(8) + 447 | "%, " + 448 | percentageOffsetY.toFixed(8) + 449 | "%) scale(" + 450 | scale.toFixed(8) + 451 | ")"; 452 | row[i].style.webkitTransform = 453 | "translate(" + 454 | percentageOffsetX.toFixed(8) + 455 | "%, " + 456 | percentageOffsetY.toFixed(8) + 457 | "%) scale(" + 458 | scale.toFixed(8) + 459 | ")"; 460 | } 461 | // transform items after 462 | var nextOffsetY = blockHeight * (scale - 1) - offsetY; 463 | var prevHeight; 464 | itemOffset = 0; // offset due to scaling of previous items 465 | prevWidth = 0; 466 | var next = row[row.length - 1].nextElementSibling; 467 | var nextRowTop = -1; 468 | while (next) { 469 | var curTop = next.offsetTop; 470 | if (curTop == nextRowTop) { 471 | itemOffset += prevWidth * scale - prevWidth; 472 | } else { 473 | if (nextRowTop != -1) { 474 | itemOffset = 0; 475 | nextOffsetY += prevHeight * (scale - 1); 476 | } 477 | nextRowTop = curTop; 478 | } 479 | prevWidth = parseInt(window.getComputedStyle(next).width, 10); 480 | prevHeight = parseInt(window.getComputedStyle(next).height, 10); 481 | var percentageOffsetX = 482 | ((itemOffset + leftOffsetX) / prevWidth) * 100; 483 | var percentageOffsetY = (nextOffsetY / prevHeight) * 100; 484 | next.style.transformOrigin = "0% 0%"; 485 | next.style.webkitTransformOrigin = "0% 0%"; 486 | next.style.transform = 487 | "translate(" + 488 | percentageOffsetX.toFixed(8) + 489 | "%, " + 490 | percentageOffsetY.toFixed(8) + 491 | "%) scale(" + 492 | scale.toFixed(8) + 493 | ")"; 494 | next.style.webkitTransform = 495 | "translate(" + 496 | percentageOffsetX.toFixed(8) + 497 | "%, " + 498 | percentageOffsetY.toFixed(8) + 499 | "%) scale(" + 500 | scale.toFixed(8) + 501 | ")"; 502 | next = next.nextElementSibling; 503 | } 504 | // transform items before 505 | var prevOffsetY = -offsetY; 506 | itemOffset = 0; // offset due to scaling of previous items 507 | prevWidth = 0; 508 | var prev = row[0].previousElementSibling; 509 | var prevRowTop = -1; 510 | while (prev) { 511 | var curTop = prev.offsetTop; 512 | if (curTop == prevRowTop) { 513 | itemOffset -= prevWidth * scale - prevWidth; 514 | } else { 515 | itemOffset = 0; 516 | prevOffsetY -= 517 | parseInt(window.getComputedStyle(prev).height, 10) * 518 | (scale - 1); 519 | prevRowTop = curTop; 520 | } 521 | prevWidth = parseInt(window.getComputedStyle(prev).width, 10); 522 | var percentageOffsetX = 523 | ((itemOffset - rightOffsetX) / prevWidth) * 100; 524 | var percentageOffsetY = 525 | (prevOffsetY / 526 | parseInt(window.getComputedStyle(prev).height, 10)) * 527 | 100; 528 | prev.style.transformOrigin = "100% 0%"; 529 | prev.style.webkitTransformOrigin = "100% 0%"; 530 | prev.style.transform = 531 | "translate(" + 532 | percentageOffsetX.toFixed(8) + 533 | "%, " + 534 | percentageOffsetY.toFixed(8) + 535 | "%) scale(" + 536 | scale.toFixed(8) + 537 | ")"; 538 | prev.style.webkitTransform = 539 | "translate(" + 540 | percentageOffsetX.toFixed(8) + 541 | "%, " + 542 | percentageOffsetY.toFixed(8) + 543 | "%) scale(" + 544 | scale.toFixed(8) + 545 | ")"; 546 | prev = prev.previousElementSibling; 547 | } 548 | }, 549 | animate: function (e) { 550 | if (this.classList.contains("active")) { 551 | zoomwall.shrink(this); 552 | } else { 553 | var actives = this.parentNode.getElementsByClassName("active"); 554 | for (var i = 0; i < actives.length; i++) { 555 | actives[i].classList.remove("active"); 556 | } 557 | zoomwall.expand(this); 558 | } 559 | e.stopPropagation(); 560 | }, 561 | reviewUrl: function (blocks) { 562 | var actives = blocks.getElementsByClassName("active"); 563 | if (actives && actives.length > 0) { 564 | var current = actives[0]; 565 | } 566 | window.open(current.attributes.reviewurl.value, "_blank").blur(); 567 | newWindow.focus(); 568 | }, 569 | profileUrl: function (blocks) { 570 | var actives = blocks.getElementsByClassName("active"); 571 | if (actives && actives.length > 0) { 572 | var current = actives[0]; 573 | } 574 | window.open(current.attributes.profileurl.value, "_blank").blur(); 575 | newWindow.focus(); 576 | }, 577 | page: function (blocks, isNext) { 578 | var actives = blocks.getElementsByClassName("active"); 579 | if (actives && actives.length > 0) { 580 | var current = actives[0]; 581 | var next; 582 | if (isNext) { 583 | next = current.nextElementSibling; 584 | } else { 585 | next = current.previousElementSibling; 586 | } 587 | if (next) { 588 | current.classList.remove("active"); 589 | // swap images 590 | if (current.dataset.lowres) { 591 | current.src = current.dataset.lowres; 592 | } 593 | zoomwall.expand(next); 594 | } 595 | } 596 | }, 597 | }; 598 | await sleep(1000); 599 | zoomwall.create(newWindow.document.getElementById("zoomwall"), true); 600 | await sleep(1000); 601 | newDoc.close(); 602 | } 603 | /////////////////////////////////////// 604 | // Button Injections // 605 | /////////////////////////////////////// 606 | /* 607 | ** Adds button to process start 608 | */ 609 | function addButts() { 610 | console.log("Adding Button"); 611 | var oldButtons = document.querySelector("#productTitle"); 612 | var newButtons = oldButtons.parentElement; 613 | var iconHtml = 614 | ''; 615 | newButtons.insertAdjacentHTML("beforeend", iconHtml); 616 | document 617 | .getElementById("ImageWallButton") 618 | .addEventListener("click", theStuff); 619 | console.log("Added Button"); 620 | } 621 | addButts(); 622 | -------------------------------------------------------------------------------- /amazonReviewWall/amzn: -------------------------------------------------------------------------------- 1 | //https://stackoverflow.com/a/58316317/8398127 2 | function getChunks(selector, strStart, strEnd) { 3 | const html = document.querySelector(selector).innerHTML; 4 | const start = html.indexOf(strStart); 5 | const end = html.indexOf(strEnd, start); 6 | 7 | if (start == -1 || end == -1) return; 8 | 9 | return { 10 | before: html.substr(0, start), 11 | match: html.substr(start, end - start + strEnd.length), 12 | after: html.substr(end + strEnd.length, html.length - end) 13 | }; 14 | } 15 | 16 | //document.documentElement.innerHTML.search('imagePopoverController.loadDataAndInitImageGalleryPopover') 17 | let chunkSelector = '#reviews-image-gallery-container > script' 18 | let chunkStart = 'data, ' 19 | let chunkEnd = '");' 20 | 21 | chunks = getChunks(chunkSelector, chunkStart, chunkEnd).match 22 | dataAndCSRF = chunks.replaceAll(');', '').replaceAll('"', '').replaceAll(' ', '') 23 | dataAndCSRFArray = dataAndCSRF.split(',') 24 | data = dataAndCSRFArray[1] 25 | firstReviewIds = dataAndCSRFArray[3] 26 | asin = data 27 | csrfToken = firstReviewIds 28 | 29 | 30 | //https://www.amazon.com/hz/reviews-render/get-reviews-with-media?mediaType=image&asin=B08DKK2KD1&csrfToken=guMT%2B0nYuIuyIIE6DbwfM0%2BcGnpEsbBr8SAKSRIAAAABAAAAAGJ5vEhyYXcAAAAA%2B4kUEk%2F7iMGR3xPcX6iU 31 | 32 | function loadReviews() { 33 | 34 | url = 'https://www.amazon.com/hz/reviews-render/get-reviews-with-media?mediaType=image&asin=' + asin + '&csrfToken=' + csrfToken 35 | 36 | 37 | function getJSON(url) { 38 | var resp; 39 | var xmlHttp; 40 | 41 | resp = ''; 42 | xmlHttp = new XMLHttpRequest(); 43 | 44 | if (xmlHttp != null) { 45 | xmlHttp.open("GET", url, false); 46 | xmlHttp.send(null); 47 | resp = xmlHttp.responseText; 48 | } 49 | 50 | return resp; 51 | } 52 | 53 | jsonGot = getJSON(url) 54 | jsonParsed = JSON.parse(jsonGot) 55 | 56 | //need to keep doing this until all pages are hit 57 | csrfToken = jsonParsed.csrfToken 58 | reviews = jsonParsed.reviewsWithMediaList 59 | 60 | reviewKeys = Object.keys(reviews) 61 | reviewCount = reviewKeys.length 62 | 63 | for (var r = 0; r < reviewCount; r++) { 64 | reviewKey = reviewKeys[r] 65 | review = reviews[reviewKey]; 66 | //console.log(review) 67 | reviewId = review.reviewId 68 | review_url = 'https://www.amazon.com/gp/customer-reviews/' + reviewId 69 | profile = 'https://www.amazon.com' + review.customerProfileLink 70 | for (var j = 0; j < review.images.length; j++) { 71 | imgurl = review.images[j].source 72 | console.log(imgurl) 73 | //console.log(csrfToken) 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /amazonReviewWall/images/amazonReviewWall.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deltabravozulu/usefulUserScripts/c3428d24fa50184479d453bf6d37f62ed3095c5a/amazonReviewWall/images/amazonReviewWall.gif -------------------------------------------------------------------------------- /amazonReviewWall/images/amazonReviewWall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deltabravozulu/usefulUserScripts/c3428d24fa50184479d453bf6d37f62ed3095c5a/amazonReviewWall/images/amazonReviewWall.png -------------------------------------------------------------------------------- /amazonReviewWall/images/amazonReviewWall_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deltabravozulu/usefulUserScripts/c3428d24fa50184479d453bf6d37f62ed3095c5a/amazonReviewWall/images/amazonReviewWall_small.png -------------------------------------------------------------------------------- /githubForkz/README.md: -------------------------------------------------------------------------------- 1 | Adds a button beside "Fork", which opens a new tab to find "Active Forks" and "Useful Forks", both websites which show cool derivatives of the current github repository you are viewing. 2 | 3 | 4 | Known Issues: This userscript might screw up with random buttons like "Sponsor". Let me know if it does. 5 | 6 | 7 | -------------------------------------------------------------------------------- /githubForkz/githubForkz.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name githubForkz 3 | // @namespace https://github.com/deltabravozulu/usefulUserScripts 4 | // @match *://github.com/*/* 5 | // @updateURL https://github.com/deltabravozulu/usefulUserScripts/raw/main/githubForkz/githubForkz.user.js 6 | // @grant none 7 | // @version 4.20.69.2022-05-09T22:04:20 8 | // @author DeltaBravoZulu 9 | // @icon data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2012.172%2015.766%22%3E%3Cpath%20d%3D%22M6.562%201.04a1.412%201.412%200%200%200-1.448%201.369v.071a1.384%201.384%200%200%200%20.76%201.266c.115%201.584-.7%201.96-2.469%202.613-.39.145-.788.294-1.186.469V2.741a1.387%201.387%200%200%200%20.731-1.249V1.48A1.41%201.41%200%200%200%202.486.413a1.5%201.5%200%200%200-.984-.362A1.41%201.41%200%200%200%20.051%201.418v.074a1.378%201.378%200%200%200%20.732%201.249v5.638a4.016%204.016%200%200%200%200%20.676v.3a1.386%201.386%200%200%200-.732%201.251v.011a1.409%201.409%200%200%200%201.389%201.434h.061a1.411%201.411%200%200%200%201.45-1.369v-.071a1.408%201.408%200%200%200-.466-1.067%201.357%201.357%200%200%200-.255-.173c0-.118%200-.239-.01-.353v-.562a.281.281%200%200%201%20.008-.031%2013.068%2013.068%200%200%201%201.679-.716c1.673-.621%203.558-1.321%203.406-4a1.388%201.388%200%200%200%20.7-1.234v-.004A1.41%201.41%200%200%200%206.624%201.04zm-5.85.444a.748.748%200%200%201%20.726-.77h.064a.748.748%200%200%201%20.785.71v.06a.749.749%200%200%201-.725.772h-.06a.75.75%200%200%201-.787-.711.62.62%200%200%201%200-.061zm1.573%209.132a.748.748%200%200%201-.724.771h-.059a.771.771%200%200%201-.05-1.542h.05a.75.75%200%200%201%20.785.712l.001.059zm4.277-7.371a.75.75%200%200%201-.786-.71v-.061a.749.749%200%200%201%20.727-.771h.059a.751.751%200%200%201%20.786.711v.06a.749.749%200%200%201-.726.771z%22%20fill%3D%22%2357a5c4%22%20stroke%3D%22%23000%22%20stroke-miterlimit%3D%2210%22%20stroke-width%3D%220.1px%22%2F%3E%3Cpath%20d%3D%22M10.716%2012.909a1.4%201.4%200%200%200-1.369%201.086%203.963%203.963%200%200%201-.911-.338%201.061%201.061%200%200%201-.245-.18.866.866%200%200%201-.123-.159q-.021-.034-.039-.069a2.054%202.054%200%200%201-.146-.358c-.054-.181-.093-.382-.132-.577l-.02-.1a4.708%204.708%200%200%200-.109-.436%202.156%202.156%200%200%200-.174-.422%201.65%201.65%200%200%200-.145-.218%201.787%201.787%200%200%200-.63-.5%201.773%201.773%200%200%200%20.63-.5%201.182%201.182%200%200%200%20.08-.11c.025-.038.039-.073.065-.106a2.152%202.152%200%200%200%20.18-.422%204.407%204.407%200%200%200%20.109-.429l.02-.1c.039-.2.078-.4.132-.577a1.912%201.912%200%200%201%20.146-.357.789.789%200%200%201%20.033-.066.827.827%200%200%201%20.123-.158%201.037%201.037%200%200%201%20.245-.181%203.911%203.911%200%200%201%20.918-.339%201.4%201.4%200%201%200-.029-.525%204.435%204.435%200%200%200-1.139.411%201.529%201.529%200%200%200-.368.276%201.471%201.471%200%200%200-.192.245l-.053.094a2.444%202.444%200%200%200-.184.453c-.06.2-.1.416-.143.622l-.02.1c-.028.135-.06.266-.1.389a1.708%201.708%200%200%201-.138.32.881.881%200%200%201-.047.077c-.016.025-.034.05-.052.074a1.5%201.5%200%200%201-.9.49l-.182.021H2.875a1.394%201.394%200%201%200-.014.6h2.952l.179.021a1.5%201.5%200%200%201%20.895.49c.019.023.036.049.052.072s.033.053.047.078a1.636%201.636%200%200%201%20.138.322c.037.123.069.253.1.389l.02.1c.04.207.083.421.143.623a2.4%202.4%200%200%200%20.187.457l.052.094a1.51%201.51%200%200%200%20.193.251%201.529%201.529%200%200%200%20.368.276%204.548%204.548%200%200%200%201.142.412%201.4%201.4%200%201%200%201.39-1.61zm0-6.836a.879.879%200%201%201-.883.879.879.879%200%200%201%20.883-.881zm-9.22%205.416a.879.879%200%201%201%20.885-.879.879.879%200%200%201-.885.879zm9.22%203.695a.88.88%200%201%201%20.884-.88.88.88%200%200%201-.884.88z%22%20fill%3D%22%23c0799a%22%20stroke%3D%22%23000%22%20stroke-miterlimit%3D%2210%22%20stroke-width%3D%220.1px%22%2F%3E%3C%2Fsvg%3E 10 | // @description Adds a button to find active and useful forks on Github 11 | // @run-at document-idle 12 | // @license PayMe 13 | // ==/UserScript== 14 | (function() { 15 | 'use strict'; 16 | 17 | try { 18 | let ulActions = Array.from(document.querySelectorAll('#repository-container-header > div.d-flex.mb-3.px-3.px-md-4.px-lg-5 >ul > li')).find(el => el.textContent.match( 'Fork')).querySelector('span').parentNode.parentNode; 19 | if (ulActions !== undefined) { 20 | let findActiveFork = document.location.pathname.substr(1).split('/'); 21 | findActiveFork = 'https://techgaun.github.io/active-forks/index.html#' + findActiveFork[0] + '/' + findActiveFork[1]; 22 | let findUsefulFork = document.location.pathname.substr(1).split('/'); 23 | findUsefulFork = 'https://useful-forks.github.io/?repo=' + findUsefulFork[0] + '/' + findUsefulFork[1]; 24 | let forkFinder=Array.from(document.querySelectorAll('#repository-container-header > div.d-flex.mb-3.px-3.px-md-4.px-lg-5 >ul > li')).find(el => el.textContent.match( 'Fork')).querySelector('span').parentNode; 25 | forkFinder.classList.add("btn-with-count") 26 | ulActions.innerHTML = ulActions.innerHTML + ` 27 |
  • 28 |
    29 | 30 | 36 | 37 | 38 | 45 | 46 |
    47 |
  • `; 48 | } 49 | } catch (e) { 50 | console.log(e); 51 | } 52 | })(); 53 | -------------------------------------------------------------------------------- /githubForkz/showActivity.js: -------------------------------------------------------------------------------- 1 | function sleep(ms) { 2 | return new Promise(resolve => setTimeout(resolve, ms)); 3 | } 4 | 5 | async function viewAllActivity() { 6 | while ( document.querySelector('#js-contribution-activity > form > button') !== null) { 7 | document.querySelector('#js-contribution-activity > form > button').click(); 8 | await sleep(1); 9 | } 10 | } 11 | 12 | 13 | yearList=document.getElementsByClassName('js-year-link')[0].parentElement.parentElement 14 | allYears=`\n
  • \n \n
  • \n ` 15 | yearList.innerHTML=allYears+yearList.innerHTML 16 | function click() {alert('hi')} 17 | document.getElementById('year-link-all').addEventListener("click",viewAllActivity) 18 | -------------------------------------------------------------------------------- /pimeyesJS/README.md: -------------------------------------------------------------------------------- 1 |

    pimeyesJS

    2 |
    Mods to make pimeyes.com work better for both premium and free users
    3 |
    4 | 14 |

    This is a UserScript written for Violent Monkey but should work on other extensions as well

    15 |
    Probably not anymore—Pimeyes has shut down good free searching :(
    16 | -------------------------------------------------------------------------------- /pimeyesJS/pimeyesJS.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name pimeyesJS 3 | // @namespace https://github.com/deltabravozulu/usefulUserScripts 4 | // @match *://pimeyes.com/en/search/* 5 | // @updateURL https://github.com/deltabravozulu/usefulUserScripts/raw/main/pimeyesJS/pimeyesJS.user.js 6 | // @grant none 7 | // @version 9.6.9_420.11 8 | // @icon https://pimeyes.com/favicon.ico 9 | // @author DeltaBravoZulu 10 | // @description Mods to make pimeyes.com work better for both premium and free users 11 | // @description 2022-05-09T18:04:20 12 | // @require https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js 13 | // @run-at document-idle 14 | // @license PayMe 15 | // ==/UserScript== 16 | /////////////////////////////////////////////////////////////////////////////////// 17 | /////////////////////////////////////////////////////////////////////////////////// 18 | //// A script to allow automatic image loading, page improvements via CSS, //// 19 | //// explicit result isolation, and other neat stuff on pimeyes.com //// 20 | //// by DeltaBravoZulu //// 21 | /////////////////////////////////////////////////////////////////////////////////// 22 | /////////////////////////////////////////////////////////////////////////////////// 23 | 24 | /////////////////////////////////////// 25 | // Script Initialization // 26 | /////////////////////////////////////// 27 | /* 28 | ** Invokes injection of buttons 29 | ** Sets initial variables and gathers stats 30 | */ 31 | 32 | //Make sure page loads before starting 33 | new MutationObserver(check).observe(document, { 34 | childList: true, 35 | subtree: true, 36 | }); 37 | 38 | function check(changes, observer) { 39 | if ( 40 | document.querySelector( 41 | "#results > div > div > div.top-slot > div > div > div > button:nth-child(5) > img" 42 | ) 43 | ) { 44 | observer.disconnect(); 45 | explicitButts(); 46 | scrollButts(); 47 | importButts(); 48 | exportButts(); 49 | explicitCount = 0; 50 | explicitStats(); 51 | scrolled = 0; 52 | //Gets the Open Graph url which was removed in June 53 | var ogUrl=document.querySelectorAll('meta[property="og:url"]')[0].content.replace('https://pimeyes.com/en','') 54 | //Adds the URL to the URL bar so you can copypaste it 55 | var newurl = window.location.protocol + "//" + window.location.host + window.location.pathname + ogUrl; 56 | window.history.pushState({path:newurl},'',newurl); 57 | //Adds scroll explicit counter 58 | scrollResultsUpdateListener(); 59 | //Adds mousedown event listener to highlight text during popup for copying 60 | clickThumb = document.querySelector("div.results-grid"); 61 | clickThumb.addEventListener("mousedown", highlightUrl); 62 | //Removes the 'Pay 299/month' overlay if hitting the Deep Search button 63 | document.querySelector("div[data-v-69882821]").remove(); 64 | //Makes rows wider and shows images better 65 | //This is broken//document.querySelector("div.results-grid").style.width="90"; 66 | document.querySelector("div.results-grid").style.minWidth="60%"; 67 | document.querySelector("div.results-grid").style.maxWidth="100%"; 68 | document.querySelector("div.results-grid").style.gridTemplateColumns = "repeat(5,20%)"; 69 | document.querySelector("div.results-grid").style.gridAutoRows = "auto"; 70 | 71 | } 72 | } 73 | 74 | //Alternative way of doing it 75 | /* 76 | var observer = new MutationObserver(resetTimer); 77 | var timer = setTimeout(action, 2000, observer); // wait for the page to stay still for 2 seconds 78 | observer.observe(document, {childList: true, subtree: true}); 79 | function resetTimer(changes, observer) { 80 | clearTimeout(timer); 81 | timer = setTimeout(action, 2000, observer); 82 | } 83 | 84 | function action(o) { 85 | o.disconnect(); 86 | observer.disconnect(); 87 | explicitButts(); 88 | scrollButts(); 89 | explicitCount = 0; 90 | explicitStats(); 91 | scrolled = 0; 92 | scrollResultsUpdateListener(); 93 | } 94 | */ 95 | 96 | /////////////////////////////////////// 97 | // Button Injections // 98 | /////////////////////////////////////// 99 | /* 100 | ** Adds buttons to invoke scrolling and removal 101 | ** Sets initial variable and gathers stats 102 | */ 103 | 104 | //Injects a button that, when pressed, will scroll to the bottom of the page to load all images, then remove all images that are not explicit 105 | function explicitButts() { 106 | console.log("Adding 18+ Button"); 107 | var oldButtons = document.querySelector( 108 | "#results > div > div > div.top-slot > div > div > div > button:last-child" 109 | ); 110 | var explicitButtons = oldButtons.parentElement; 111 | var iconHtml = 112 | ''; 113 | explicitButtons.insertAdjacentHTML("beforeend", iconHtml); 114 | document.getElementById("18Button").addEventListener("click", explicitJS); 115 | console.log("Added 18+ Button"); 116 | } 117 | 118 | //Injects a scroll button which will allow one to load all images on the page automatically 119 | function scrollButts() { 120 | console.log("Adding Scroll Button"); 121 | var oldButtons = document.querySelector( 122 | "#results > div > div > div.top-slot > div > div > div > button:last-child" 123 | ); 124 | var scrollButton = oldButtons.parentElement; 125 | var scrollIconHtml = 126 | ''; 127 | scrollButton.insertAdjacentHTML("beforeend", scrollIconHtml); 128 | document.getElementById("scrollButton").addEventListener("click", betterScroller); 129 | console.log("Added Scroll Button"); 130 | } 131 | 132 | //Injects a button that, when pressed, will copy the Open Graph index to the clipboard 133 | function exportButts() { 134 | console.log("Adding OG URL Export Button"); 135 | var oldButtons = document.querySelector( 136 | "#results > div > div > div.top-slot > div > div > div > button:last-child" 137 | ); 138 | var exportButton = oldButtons.parentElement; 139 | var exportIconHtml = 140 | ''; 141 | scrollButton.insertAdjacentHTML("afterend", exportIconHtml); 142 | document.getElementById("exportButton").addEventListener("click", exporter); 143 | console.log("Added Export Button"); 144 | } 145 | 146 | //Injects a button that, when pressed, will paste the Open Graph index from the clipboard to the URL bar 147 | function importButts() { 148 | console.log("Adding OG URL Import Button"); 149 | var oldButtons = document.querySelector( 150 | "#results > div > div > div.top-slot > div > div > div > button:last-child" 151 | ); 152 | var importButton = oldButtons.parentElement; 153 | var importIconHtml = 154 | ''; 155 | scrollButton.insertAdjacentHTML("afterend", importIconHtml); 156 | document.getElementById("importButton").addEventListener("click", importer); 157 | console.log("Added Import Button"); 158 | } 159 | 160 | 161 | /////////////////////////////////////// 162 | // Export/Import OpenGraph Url // 163 | /////////////////////////////////////// 164 | /* 165 | ** Includes a scroller to load the page, stats, and sleep timers 166 | */ 167 | 168 | //Copies the open graph url to the clipboard 169 | 170 | ogUrl=document.querySelectorAll('meta[property="og:url"]')[0].content.replace('https://pimeyes.com/en','') 171 | ogUrlCut=ogUrl.substring(0, ogUrl.lastIndexOf('?')).replace('/search/','') 172 | 173 | function exporter() { 174 | executeCopy = function() { 175 | var copyhelper = document.createElement("input"); 176 | copyhelper.className = 'copyhelper' 177 | document.body.appendChild(copyhelper); 178 | copyhelper.value = ogUrlCut; 179 | copyhelper.select(); 180 | document.execCommand("copy"); 181 | document.body.removeChild(copyhelper); 182 | }; 183 | executeCopy(); 184 | console.log("ogURLCut is " + ogUrlCut) 185 | } 186 | 187 | async function importer() { 188 | oldPage=window.location.href; 189 | oldPageIndex=oldPage.indexOf(ogUrlCut) 190 | ogUrlImport= await navigator.clipboard.readText(); 191 | newPage=oldPage.substr(0, oldPageIndex) + ogUrlImport + "_" + oldPage.substr(oldPageIndex) 192 | console.log("oldPage is " + oldPage) 193 | console.log("newPage is " + newPage) 194 | window.history.pushState({path:newPage},'',newPage); 195 | window.location.href=newPage 196 | } 197 | 198 | 199 | 200 | /////////////////////////////////////// 201 | // Removal Prerequisites // 202 | /////////////////////////////////////// 203 | /* 204 | ** Includes a scroller to load the page, stats, and sleep timers 205 | */ 206 | 207 | //Scrolls down the page as fast as possible 208 | function scrollDown() { 209 | window.scrollBy(0, 10000); 210 | window.scrollTo(0, document.body.scrollHeight); 211 | } 212 | 213 | //Scrolls to the top of the page 214 | function scrollUp() { 215 | window.scrollBy(0, -50000); 216 | window.scrollTo(0, 0); 217 | } 218 | 219 | //Scrolls all the way to the bottom of the page to load all results, then scrolls back to the top 220 | async function scroller() { 221 | if (document.querySelectorAll("div.results-end").length === 1) { 222 | scrolled = 1; 223 | } else if (document.querySelectorAll("div.results-end").length === 0) { 224 | scrolled = 0; 225 | } 226 | while (scrolled < 1) { 227 | console.log("Scrolling to the bottom of the results"); 228 | var scrollCount = 1; 229 | do { 230 | scrollDown(); 231 | console.log("Sleeping 1000ms"); 232 | await sleep(1000); 233 | console.log("Still scrolling (" + scrollCount + "x)"); 234 | scrollCount++; 235 | } while (document.querySelectorAll("div.results-end").length === 0); 236 | console.log("Done scrolling"); 237 | console.log("Sleeping 1000ms"); 238 | await sleep(1000); 239 | console.log("Scrolling to top of page"); 240 | scrollUp(); 241 | console.log("We reached the top"); 242 | console.log("Sleeping 1000ms"); 243 | await sleep(1000); 244 | scrolled = 1; 245 | } 246 | } 247 | 248 | //Scrolls but lets you control it 249 | function betterScroller() { 250 | var a = document.body.clientHeight, 251 | b = document.documentElement.scrollHeight, 252 | c = document.documentElement.clientHeight, 253 | d = innerHeight, 254 | e = document.height; 255 | if (console.log("document.body.clientHeight:\t\t\t\t\t" + a + ";\ndocument.documentElement.scrollHeight:\t\t" + b + ";\ndocument.documentElement.clientHeight:\t\t" + c + ";\ninnerHeight:\t\t\t\t\t\t\t\t" + d + ";\ndocument.height:\t\t\t\t\t\t\t" + e), document.URL.includes("facebook.com")) ! function() { 256 | var e = null, 257 | t = 0, 258 | s = function() { 259 | console.log("Clicked; stopping autoscroll"), clearInterval(e), document.body.removeEventListener("click", s) 260 | }; 261 | document.body.addEventListener("click", s), e = setInterval(function() { 262 | var o = document.body.scrollHeight - document.body.scrollTop - window.innerHeight; 263 | o > 0 ? (window.scrollBy(0, o), t > 0 && (t = 0), console.log("scrolling down more")) : t >= 3 ? (console.log("reached bottom of page; stopping"), clearInterval(e), document.body.removeEventListener("click", s)) : (console.log("[apparenty] hit bottom of page; retrying: " + (t + 1)), t++) 264 | }, 1e3) 265 | }(); 266 | else { 267 | let e, t = 1, 268 | s = [ 269 | [0, 0], 270 | [25, 200], 271 | [36, 120], 272 | [49, 72], 273 | [64, 43.2], 274 | [81, 25.9], 275 | [100, 31], 276 | [121, 37.2], 277 | [144, 44.8], 278 | [169, 26.4], 279 | [196, 32] 280 | ], 281 | o = document.onkeypress; 282 | _ss_stop = function() { 283 | clearTimeout(e) 284 | }, _ss_start = function() { 285 | _ss_abs_speed = Math.abs(t), _ss_direction = t / _ss_abs_speed, _ss_speed_pair = s[_ss_abs_speed], e = setInterval("scrollBy(0," + _ss_direction * _ss_speed_pair[0] + "); if((pageYOffset<=1)||(pageYOffset==document.documentElement.scrollHeight-innerHeight)) _ss_speed=0;", _ss_speed_pair[1]) 286 | }, _ss_adj = function(e) { 287 | t += e, Math.abs(t) >= s.length && (t = (s.length - 1) * (t / Math.abs(t))) 288 | }, _ss_quit = function() { 289 | _ss_stop(), document.onkeypress = o 290 | }, document.onkeypress = function(e) { 291 | if (113 != e.charCode && 27 != e.keyCode) { 292 | if (e.charCode >= 48 && e.charCode <= 57) t = e.charCode - 48; 293 | else switch (e.charCode) { 294 | case 95: 295 | _ss_adj(-2); 296 | case 45: 297 | _ss_adj(-1); 298 | break; 299 | case 43: 300 | _ss_adj(2); 301 | case 61: 302 | _ss_adj(1) 303 | } 304 | _ss_stop(), _ss_start() 305 | } else _ss_quit() 306 | }, _ss_stop(), _ss_start() 307 | } 308 | } 309 | 310 | //Lets script sleep after functions to allow page a bit of time to catch up 311 | function sleep(ms) { 312 | return new Promise((resolve) => setTimeout(resolve, ms)); 313 | } 314 | 315 | //Helper script to update the count of explicit results 316 | function expResultsUpdater() { 317 | explicitCount = document.querySelectorAll( 318 | "#results div.results-grid div.result div.thumbnail span.explicit-result" 319 | ).length; 320 | console.log(explicitCount + " potentially explicit results so far"); 321 | document.getElementById("expResults").innerHTML = explicitCount; 322 | } 323 | 324 | //Injects an explicit results running total at the top of the page 325 | function explicitStats() { 326 | console.log("Inserting Stats Counter"); 327 | var oldResults = document.querySelector( 328 | "#results > div.container > div > div.top-slot > div > div.container > span.stats > span:nth-child(1)" 329 | ); 330 | var explicitResults = oldResults; 331 | var resultsHtml = 332 | '' + 333 | '' + 334 | explicitCount + 335 | "" + 336 | " potentially explicit results so far"; 337 | explicitResults.insertAdjacentHTML("beforebegin", resultsHtml); 338 | expResultsUpdater(); 339 | } 340 | 341 | //Updates the explicit results count that was injected at the top of the page then stops doing anything after page-end is reached 342 | function scrollResultsUpdateListener() { 343 | addEventListener("scroll", function () { 344 | if (document.querySelectorAll("div.results-end").length === 0) { 345 | expResultsUpdater(); 346 | scrolled = 0; 347 | } 348 | }); 349 | } 350 | 351 | 352 | 353 | //Highlights and generates url to go to site where image is hosted 354 | async function highlightUrl() { 355 | console.log("Waiting to highlight"); 356 | await sleep(200); 357 | var spanUrl = document.querySelector( 358 | "div.modal-content div.thumbnail span.url" 359 | ); 360 | if (typeof spanUrl != "undefined" && spanUrl != null) { 361 | spanUrl = document.querySelector( 362 | "div.modal-content div.thumbnail span.url" 363 | ); 364 | spanUrl.innerHTML = 365 | `` + spanUrl.innerHTML + ``; 366 | 367 | function selectText(node) { 368 | node = spanUrl; 369 | 370 | if (document.body.createTextRange) { 371 | const range = document.body.createTextRange(); 372 | range.moveToElementText(node); 373 | range.select(); 374 | } else if (window.getSelection) { 375 | const selection = window.getSelection(); 376 | const range = document.createRange(); 377 | range.selectNodeContents(node); 378 | selection.removeAllRanges(); 379 | selection.addRange(range); 380 | } else { 381 | console.warn( 382 | "Could not select text in node: Unsupported browser." 383 | ); 384 | } 385 | } 386 | selectText("spanUrl"); 387 | } else { 388 | console.log( 389 | "Tried to highlight URL because of highlightUrl mousedown event listener but popup does not exist!" 390 | ); 391 | } 392 | } 393 | 394 | /////////////////////////////////////// 395 | // Removal Scripts // 396 | /////////////////////////////////////// 397 | /* 398 | **Pure Javascript based removal scripts 399 | */ 400 | 401 | //Script to remove nonexplicit images using jQuery 402 | function jsRemover() { 403 | console.log("Running removal script (Pure JavaScript)"); 404 | document 405 | .querySelectorAll("#results div.results-grid div.result div.thumbnail") 406 | .forEach(function (element) { 407 | if (!element.querySelector("span.explicit-result")) { 408 | element.parentNode.remove(); 409 | } 410 | }); 411 | console.log("Finished removal script"); 412 | } 413 | 414 | //jsRemover helper script 415 | async function explicitJS() { 416 | console.log("Starting the removal process"); 417 | await scroller(); 418 | jsRemover(); 419 | console.log("Finished the removal process"); 420 | } 421 | 422 | /* 423 | **jQuery based removal scripts 424 | */ 425 | 426 | //Script to remove nonexplicit images using jQuery 427 | function jqRemover() { 428 | console.log("Running removal service (jQuery)"); 429 | jQuery( 430 | "#results div.results-grid div.result div.thumbnail:has(span):not(:has(.explicit-result))" 431 | ) 432 | .parent() 433 | .remove(); 434 | console.log("Finished removal script"); 435 | } 436 | 437 | //jqRemover helper script 438 | async function explicitJQ() { 439 | jqGetter(); 440 | console.log("Starting the removal process"); 441 | await scroller(); 442 | jsRemover(); 443 | console.log("Finished the removal process"); 444 | } 445 | 446 | //Downloads jQuery to the page 447 | function jqGetter() { 448 | console.log("Downloading jQuery to page"); 449 | var el = document.createElement("div"), 450 | b = document.getElementsByTagName("body")[0], 451 | otherlib = !1, 452 | msg = ""; 453 | (el.style.position = "fixed"), 454 | (el.style.height = "32px"), 455 | (el.style.width = "220px"), 456 | (el.style.marginLeft = "-110px"), 457 | (el.style.top = "0"), 458 | (el.style.left = "50%"), 459 | (el.style.padding = "5px 10px"), 460 | (el.style.zIndex = 1001), 461 | (el.style.fontSize = "12px"), 462 | (el.style.color = "#222"), 463 | (el.style.backgroundColor = "#f99"); 464 | 465 | function showMsg() { 466 | var txt = document.createTextNode(msg); 467 | el.appendChild(txt), 468 | b.appendChild(el), 469 | window.setTimeout(function () { 470 | (txt = null), 471 | typeof jQuery == "undefined" 472 | ? b.removeChild(el) 473 | : (jQuery(el).fadeOut("slow", function () { 474 | jQuery(this).remove(); 475 | }), 476 | otherlib && (window.$jq = jQuery.noConflict())); 477 | }, 2500); 478 | } 479 | if (typeof jQuery != "undefined") 480 | return ( 481 | (msg = "This page already using jQuery v" + jQuery.fn.jquery), 482 | showMsg() 483 | ); 484 | typeof $ == "function" && (otherlib = !0); 485 | 486 | function getScript(url, success) { 487 | var script = document.createElement("script"); 488 | script.src = url; 489 | var head = document.getElementsByTagName("head")[0], 490 | done = !1; 491 | (script.onload = script.onreadystatechange = function () { 492 | !done && 493 | (!this.readyState || 494 | this.readyState == "loaded" || 495 | this.readyState == "complete") && 496 | ((done = !0), 497 | success(), 498 | (script.onload = script.onreadystatechange = null), 499 | head.removeChild(script)); 500 | }), 501 | head.appendChild(script); 502 | } 503 | getScript("//code.jquery.com/jquery.min.js", function () { 504 | return ( 505 | typeof jQuery == "undefined" 506 | ? (msg = "Sorry, but jQuery was not able to load") 507 | : ((msg = 508 | "This page is now jQuerified with v" + 509 | jQuery.fn.jquery), 510 | otherlib && 511 | (msg += " and noConflict(). Use $jq(), not $().")), 512 | showMsg() 513 | ); 514 | }); 515 | console.log("jQuery downloaded to page"); 516 | } 517 | 518 | /////////////////////////////////////// 519 | // CSS Mods/Page Improvement // 520 | /////////////////////////////////////// 521 | /** 522 | * Utility function to add CSS in multiple passes. 523 | * @param {string} styleString 524 | * From http://stackoverflow.com/a/15506705 525 | **/ 526 | function addStyle(styleString) { 527 | const style = document.createElement("style"); 528 | style.textContent = styleString; 529 | document.head.append(style); 530 | } 531 | 532 | //From https://greasyfork.org/scripts/406062 533 | addStyle(` 534 | /*Un-blur the URLs*/ 535 | .blurred-source-url { 536 | user-select: all !important; 537 | ; 538 | } 539 | `); 540 | 541 | //From https://greasyfork.org/scripts/406062 542 | /*div.modal-content>div.thumbnail>span.url*/ 543 | 544 | addStyle(` 545 | /*Make the URLs selectable, and visible*/ 546 | *.url { 547 | filter: none !important; 548 | ; 549 | overflow: visible !important; 550 | ; 551 | user-select: initial !important; 552 | ; 553 | max-width: initial !important; 554 | ; 555 | pointer-events: none !important; 556 | ; 557 | position: initial !important; 558 | } 559 | `); 560 | 561 | //From https://greasyfork.org/scripts/406062 562 | addStyle(` 563 | /*Remove the Buy Premium overlay on images*/ 564 | .zoom { 565 | display: none !important; 566 | ; 567 | } 568 | `); 569 | 570 | //From https://greasyfork.org/scripts/406062 571 | addStyle(` 572 | /*Remove the 'Get access to archival results and Deep search for $299.99/mo overlay on images*/ 573 | .promo { 574 | display: none !important; 575 | ; 576 | } 577 | `); 578 | 579 | //From https://greasyfork.org/scripts/406062 580 | addStyle(` 581 | /*Remove the actions menu, so we can select the image*/ 582 | .actions { 583 | display: none !important; 584 | ; 585 | } 586 | `); 587 | 588 | //From https://greasyfork.org/scripts/406062 589 | /* 590 | addStyle(` 591 | /*Hide UNLOCK buttons*\/ 592 | button[type="button"] { 593 | display: none !important; 594 | ; 595 | } 596 | `); 597 | */ 598 | 599 | //From https://greasyfork.org/scripts/406062 600 | addStyle(` 601 | /*un-hide add picture button*/ 602 | button[class="spacer"] { 603 | display: inherit !important; 604 | ; 605 | } 606 | `); 607 | 608 | //From https://greasyfork.org/scripts/406062 609 | addStyle(` 610 | /*Remove events from image*/ 611 | div.thumbnail { 612 | pointer-events: none !important; 613 | ; 614 | } 615 | `); 616 | 617 | addStyle(` 618 | /*Hide the unlock popup/buttons if it appears*/ 619 | #app > div:nth-child(4) > div > div.mask { 620 | display: none !important; 621 | ; 622 | } 623 | `); 624 | 625 | addStyle(` 626 | /*Hide the unlock popup/buttons if it appears*/ 627 | #app > div:nth-child(4) > div.wrapper { 628 | display: none !important; 629 | ; 630 | } 631 | `); 632 | 633 | //Hide the unlock popup if it appears in another way (e.g. hitting Deep search on a paid account) 634 | //Prevent block-scroll from impacting the body if one hits "Deep search" or any button which causes an overlay 635 | addStyle(` 636 | /*Hide the unlock popup if it appears in another way#1*/ 637 | /*Prevent block-scroll from impacting the body if one hits "Deep search" or any button which causes an overlay*/ 638 | .block-scroll { 639 | touch-action: auto !important; 640 | -webkit-overflow-scrolling: touch!important; 641 | overflow: visible!important; 642 | -ms-scroll-chaining: none!important; 643 | overscroll-behavior: unset!important; 644 | } 645 | `); 646 | 647 | 648 | //Stops the button sizes from changing if one happens to hit the Deep Search button or cause an overlay 649 | addStyle(` 650 | /*Hide the unlock popup if it appears in another way #2*/ 651 | /*Stops the button sizes from changing if one happens to hit the Deep Search button or cause an overlay*/ 652 | *, :after, :before { 653 | box-sizing: revert !important; 654 | } 655 | `); 656 | 657 | addStyle(` 658 | /*Hide the Formspring payment request*/ 659 | #fscCanvas { 660 | display: none !important; 661 | ; 662 | } 663 | `); 664 | 665 | addStyle(` 666 | /*Prevent the overlays from blocking scrolling* 667 | body { 668 | overflow: visible !important; 669 | ; 670 | } 671 | `); 672 | 673 | /* 674 | ** bookmarklet 675 | javascript:(function()%7Beval(function(p%2Ca%2Cc%2Ck%2Ce%2Cr)%7Be%3Dfunction(c)%7Breturn(c%3Ca%3F''%3Ae(parseInt(c%2Fa)))%2B((c%3Dc%25a)%3E35%3FString.fromCharCode(c%2B29)%3Ac.toString(36))%7D%3Bif(!''.replace(%2F%5E%2F%2CString))%7Bwhile(c--)r%5Be(c)%5D%3Dk%5Bc%5D%7C%7Ce(c)%3Bk%3D%5Bfunction(e)%7Breturn%20r%5Be%5D%7D%5D%3Be%3Dfunction()%7Breturn'%5C%5Cw%2B'%7D%3Bc%3D1%7D%3Bwhile(c--)if(k%5Bc%5D)p%3Dp.replace(new%20RegExp('%5C%5Cb'%2Be(c)%2B'%5C%5Cb'%2C'g')%2Ck%5Bc%5D)%3Breturn%20p%7D('b%201q()%7B7.8(%221r%2018%2B%20u%22)%3B5.k(%22%23c%20%3E%203%20%3E%203%20%3E%203.w-Z%20%3E%203%20%3E%203%20%3E%203%20%3E%20g%3A1s-y%22).1t.10(%221u%22%2C%5C'%3Cg%20h-v-m%3D%22%22%201v%3D%22g%22%2011%3D%221w%201x-1y%22%20h-v-1z%3D%22%22%2012%3D%221A%22%3E%3C1B%20h-v-m%3D%22%22%201C%3D%22h%3AH%2F1D%2B1E%3B1F%2C2q%2B2r%2B2s%2B%22%3E%20%3Cf%20h-v-m%3D%22%22%3E2t%202u%3C%2Ff%3E%3C%2Fg%3E%5C')%2C5.13(%221A%22).I(%221G%22%2C1H)%2C7.8(%221I%2018%2B%20u%22)%7Db%201J()%7B7.8(%221r%2014%20u%22)%3B5.k(%22%23c%20%3E%203%20%3E%203%20%3E%203.w-Z%20%3E%203%20%3E%203%20%3E%203%20%3E%20g%3A1s-y%22).1t.10(%221u%22%2C%5C'%3Cg%20h-v-m%3D%22%22%201v%3D%22g%22%2011%3D%221w%201x-1y%22%20h-v-1z%3D%22%22%2012%3D%221K%22%3E%3C1B%20h-v-m%3D%22%22%201C%3D%22h%3AH%2F1D%2B1E%3B1F%2C2v%2B2w%3D%3D%22%3E%20%3Cf%20h-v-m%3D%22%22%3E14%20u%3C%2Ff%3E%3C%2Fg%3E%5C')%2C5.13(%221K%22).I(%221G%22%2C15)%2C7.8(%221I%2014%20u%22)%7Db%201L()%7Bo.1M(0%2C2x)%2Co.1N(0%2C5.J.2y)%7Db%201O()%7Bo.1M(0%2C-2z)%2Co.1N(0%2C0)%7D16%20b%2015()%7B1P(1%3D%3D%3D5.p(%223.c-K%22).z%3Fq%3D1%3A0%3D%3D%3D5.p(%223.c-K%22).z%26%26(q%3D0)%3Bq%3C1%3B)%7B7.8(%221Q%20r%209%202A%2017%209%20c%22)%3B19%20e%3D1%3B2B%7B1L()%2C7.8(%221a%201b%22)%2CA%20B(1c)%2C7.8(%222C%20L%20(%22%2Be%2B%22x)%22)%2Ce%2B%2B%7D2D(0%3D%3D%3D5.p(%223.c-K%22).z)%3B7.8(%222E%20L%22)%2C7.8(%221a%201b%22)%2CA%20B(1c)%2C7.8(%221Q%20r%20w%2017%202F%22)%2C1O()%2C7.8(%222G%202H%209%20w%22)%2C7.8(%221a%201b%22)%2CA%20B(1c)%2Cq%3D1%7D%7Db%20B(e)%7B2I%202J%202K(t%3D%3E2L(t%2Ce))%7Db%201d()%7BC%3D5.p(%22%23c%203.c-1e%203.M%203.s%20f.N-M%22).z%2C7.8(C%2B%22%201R%20N%20c%201f%201S%22)%2C5.13(%221T%22).O%3DC%7Db%201U()%7B7.8(%222M%202N%202O%22)%3B19%20e%3D5.k(%22%23c%20%3E%203%20%3E%203%20%3E%203.w-Z%20%3E%203%20%3E%203%20%3E%20f%20%3E%20f%3A1g-y(2)%22)%2Ct%3D%5C'%3Cf%20h-v-2P%3D%22%22%3E%3C1V%2012%3D%221T%22%3E%5C'%2BC%2B%22%3C%2F1V%3E%201R%20N%20c%201f%201S%3C%2Ff%3E%22%3Be.10(%222Q%22%2Ct)%2C1d()%7Db%201W()%7BI(%22P%22%2Cb()%7B0%3D%3D%3D5.p(%223.c-K%22).z%26%26(1d()%2Cq%3D0)%7D)%7D16%20b%201h()%7B7.8(%222R%20r%201X%22)%2CA%20B(2S)%3B19%20e%3D5.k(%223.1i-1j%203.s%20f.D%22)%3Bj(2T%200!%3D%3De%26%262U!%3De)%7B(e%3D5.k(%223.1i-1j%203.s%20f.D%22)).O%3D%5C'%3Ca%202V%3D%22%5C'%2Be.O%2B%5C'%22%3E%5C'%2Be.O%2B%22%3C%2Fa%3E%22%2Cb(t)%7Bj(t%3De%2C5.J.1Y)%7B1k%20e%3D5.J.1Y()%3Be.2W(t)%2Ce.E()%7D1l%20j(o.1Z)%7B1k%20e%3Do.1Z()%2Cn%3D5.2X()%3Bn.2Y(t)%2Ce.2Z()%2Ce.30(n)%7D1l%207.31(%2232%2020%20E%2033%201m%2034%3A%2035%2036.%22)%7D(%2237%22)%7D1l%207.8(%2238%20r%201X%2039%203a%2017%201h%2021%203b%203c%203d%20F%203e%2020%203f!%22)%7Db%2022()%7B7.8(%223g%20Q%2023%20(3h%203i)%22)%2C5.p(%22%23c%203.c-1e%203.M%203.s%22).3j(b(e)%7Be.k(%22f.N-M%22)%7C%7Ce.3k.24()%7D)%2C7.8(%2225%20Q%2023%22)%7D16%20b%201H()%7B7.8(%223l%209%20Q%2026%22)%2CA%2015()%2C22()%2C7.8(%2225%209%20Q%2026%22)%7Db%20d(e)%7B1k%20t%3D5.3m(%223n%22)%3Bt.3o%3De%2C5.3p.3q(t)%7D1q()%2C1J()%2CC%3D0%2C1U()%2Cq%3D0%2C1W()%2C27%3D5.k(%223.c-1e%22)%2C27.I(%2221%22%2C1h)%2Cd(%22%5C%5Cn%2F*3r-3s%209%2028*%2F%5C%5Cn.3t-3u-D%20%7B%5C%5Cn%20%20%20%2029-E%3A%203v%20!6%3B%5C%5Cn%20%20%20%20%3B%5C%5Cn%7D%5C%5Cn%22)%2Cd(%22%5C%5Cn%2F*3w%209%2028%203x%2C%202a%20R*%2F%5C%5Cn%2F*3.1i-1j%3E3.s%3Ef.D*%2F%5C%5Cn*.D%20%7B%5C%5Cn%20%20%20%203y%3A%20i%20!6%3B%5C%5Cn%20%20%20%20%3B%5C%5Cn%20%20%20%20S%3A%20R%20!6%3B%5C%5Cn%20%20%20%20%3B%5C%5Cn%20%20%20%2029-E%3A%201n%20!6%3B%5C%5Cn%20%20%20%20%3B%5C%5Cn%20%20%20%203z-3A%3A%201n%20!6%3B%5C%5Cn%20%20%20%20%3B%5C%5Cn%20%20%20%202b-1o%3A%20i%20!6%3B%5C%5Cn%20%20%20%20%3B%5C%5Cn%20%20%20%203B%3A%201n%20!6%3B%5C%5Cn%7D%5C%5Cn%22)%2Cd(%22%5C%5Cn%2F*T%209%203C%203D%20U%202c%202d*%2F%5C%5Cn.3E%20%7B%5C%5Cn%20%20%20%20l%3A%20i%20!6%3B%5C%5Cn%20%20%20%20%3B%5C%5Cn%7D%5C%5Cn%22)%2Cd(%22%5C%5Cn%2F*T%209%20%5C'3F%203G%20r%203H%20c%202a%201p%202e%201P%20%243I.3J%2F3K%20U%202c%202d*%2F%5C%5Cn.3L%20%7B%5C%5Cn%20%20%20%20l%3A%20i%20!6%3B%5C%5Cn%20%20%20%20%3B%5C%5Cn%7D%5C%5Cn%22)%2Cd(%22%5C%5Cn%2F*T%209%202f%203M%2C%201f%203N%203O%20E%209%20H*%2F%5C%5Cn.2f%20%7B%5C%5Cn%20%20%20%20l%3A%20i%20!6%3B%5C%5Cn%20%20%20%20%3B%5C%5Cn%7D%5C%5Cn%22)%2Cd(%5C'%5C%5Cn%2F*3P-3Q%203R%203S%20g*%2F%5C%5C3T%5B11%3D%223U%22%5D%20%7B%5C%5Cn%20%20%20%20l%3A%203V%20!6%3B%5C%5Cn%20%20%20%20%3B%5C%5Cn%7D%5C%5Cn%5C')%2Cd(%22%5C%5Cn%2F*T%201o%20V%20H*%2F%5C%5C3W.s%20%7B%5C%5Cn%20%20%20%202b-1o%3A%20i%20!6%3B%5C%5Cn%20%20%20%20%3B%5C%5Cn%7D%5C%5Cn%22)%2Cd(%22%5C%5Cn%2F*G%209%20W%20F%2F2g%20j%20X%20Y*%2F%5C%5Cn%232h%20%3E%203%3A1g-y(4)%20%3E%203%20%3E%203.3X%20%7B%5C%5Cn%20%20%20%20l%3A%20i%20!6%3B%5C%5Cn%20%20%20%20%3B%5C%5Cn%7D%5C%5Cn%22)%2Cd(%22%5C%5Cn%2F*G%209%20W%20F%2F2g%20j%20X%20Y*%2F%5C%5Cn%232h%20%3E%203%3A1g-y(4)%20%3E%203.3Y%20%7B%5C%5Cn%20%20%20%20l%3A%20i%20!6%3B%5C%5Cn%20%20%20%20%3B%5C%5Cn%7D%5C%5Cn%22)%2Cd(%5C'%5C%5Cn%2F*G%209%20W%20F%20j%20X%20Y%201m%202i%202j%231*%2F%5C%5Cn%2F*2k%202l-P%20V%203Z%209%20J%20j%202m%2040%20%221p%202e%22%202n%2041%20g%2042%2043%202o%20U*%2F%5C%5Cn.2l-P%20%7B%5C%5Cn%20%20%20%202p-44%3A%2045%20!6%3B%5C%5Cn%20%20%20%20-46-S-L%3A%202p!6%3B%5C%5Cn%20%20%20%20S%3A%20R!6%3B%5C%5Cn%20%20%20%20-47-P-48%3A%20i!6%3B%5C%5Cn%20%20%20%2049-4a%3A%204b!6%3B%5C%5Cn%7D%5C%5Cn%5C%5Ct%5C')%2C5.k(%223%5Bh-v-4c%5D%22).24()%2Cd(%22%5C%5Cn%2F*G%209%20W%20F%20j%20X%20Y%201m%202i%202j%20%232*%2F%5C%5Cn%2F*4d%209%20g%204e%20V%204f%20j%202m%204g%20r%204h%209%201p%204i%20g%202n%204j%202o%20U*%2F%5C%5Cn*%2C%20%3A4k%2C%20%3A4l%20%7B%5C%5Cn%20%20%20%204m-4n%3A%204o%20!6%3B%5C%5Cn%7D%5C%5Cn%22)%2Cd(%22%5C%5Cn%2F*G%209%204p%204q%204r*%2F%5C%5Cn%234s%20%7B%5C%5Cn%20%20%20%20l%3A%20i%20!6%3B%5C%5Cn%20%20%20%20%3B%5C%5Cn%7D%5C%5Cn%22)%2Cd(%22%5C%5Cn%2F*2k%209%204t%20V%204u%20L*%5C%5C4v%20%7B%5C%5Cn%20%20%20%20S%3A%20R%20!6%3B%5C%5Cn%20%20%20%20%3B%5C%5Cn%7D%5C%5Cn%22)%3B'%2C62%2C280%2C'%7C%7C%7Cdiv%7C%7Cdocument%7Cimportant%7Cconsole%7Clog%7Cthe%7C%7Cfunction%7Cresults%7CaddStyle%7C%7Cspan%7Cbutton%7Cdata%7Cnone%7Cif%7CquerySelector%7Cdisplay%7C4ccff48d%7C%7Cwindow%7CquerySelectorAll%7Cscrolled%7Cto%7Cthumbnail%7C%7CButton%7C%7Ctop%7C%7Cchild%7Clength%7Cawait%7Csleep%7CexplicitCount%7Curl%7Cselect%7Cpopup%7CHide%7Cimage%7CaddEventListener%7Cbody%7Cend%7Cscrolling%7Cresult%7Cexplicit%7CinnerHTML%7Cscroll%7Cremoval%7Cvisible%7Coverflow%7CRemove%7Coverlay%7Cfrom%7Cunlock%7Cit%7Cappears%7Cslot%7CinsertAdjacentHTML%7Cclass%7Cid%7CgetElementById%7CScroll%7Cscroller%7Casync%7Cof%7C%7Cvar%7CSleeping%7C1000ms%7C1e3%7CexpResultsUpdater%7Cgrid%7Cso%7Cnth%7ChighlightUrl%7Cmodal%7Ccontent%7Cconst%7Celse%7Cin%7Cinitial%7Cevents%7CDeep%7CexplicitButts%7CAdding%7Clast%7CparentElement%7Cbeforeend%7Ctype%7Cdefault%7Cicon%7Conly%7C46dbee4d%7C18Button%7Cimg%7Csrc%7Csvg%7Cxml%7Cbase64%7Cclick%7CexplicitJS%7CAdded%7CscrollButts%7CscrollButton%7CscrollDown%7CscrollBy%7CscrollTo%7CscrollUp%7Cfor%7CScrolling%7Cpotentially%7Cfar%7CexpResults%7CexplicitStats%7Cbdi%7CscrollResultsUpdateListener%7Chighlight%7CcreateTextRange%7CgetSelection%7Cnot%7Cmousedown%7CjsRemover%7Cscript%7Cremove%7CFinished%7Cprocess%7CclickThumb%7CURLs%7Cuser%7Cand%7Cpointer%7Con%7Cimages%7Csearch%7Cactions%7Cbuttons%7Capp%7Canother%7Cway%7CPrevent%7Cblock%7Cone%7Cor%7Can%7Ctouch%7CPHN2ZyB2aWV3Qm94PSIwIDAgMzEwLjkgMzEwLjkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI%7CPHBhdGggZD0iTTk1IDIxMS40di04OS4zSDc0LjRWOTkuMmg0OS4xdjExMi4yem0xMzUuNi04My4yYzAgOS44LTUuMyAxOC40LTE0LjEgMjMuMiAxMi4zIDUuMSAyMCAxNS44IDIwIDI4LjMgMCAyMC4yLTE3LjkgMzMtNDUuOSAzM3MtNDUuOS0xMi42LTQ1LjktMzIuNWMwLTEyLjggOC4zLTIzLjcgMjEuMy0yOC44LTkuNC01LjMtMTUuNS0xNC4yLTE1LjUtMjQgMC0xNy45IDE1LjctMjkuMyA0MC0yOS4zIDI0LjUuMSA0MC4xIDExLjcgNDAuMSAzMC4xem0tNTkuMSA0OS4yYzAgOS40IDYuNyAxNC43IDE5IDE0LjdzMTkuMi01LjEgMTkuMi0xNC43YzAtOS4zLTYuOS0xNC42LTE5LjItMTQuNnMtMTkgNS4zLTE5IDE0LjZ6bTIuOS00Ny42YzAgOCA1LjggMTIuNSAxNi4yIDEyLjVzMTYuMi00LjUgMTYuMi0xMi41YzAtOC4zLTUuOC0xMy0xNi4yLTEzLTEwLjUuMS0xNi4yIDQuNy0xNi4yIDEzeiIvPjxwYXRoIGQ9Ik0xNTUuNCAzMTAuOUM2OS43IDMxMC45IDAgMjQxLjEgMCAxNTUuNFM2OS43IDAgMTU1LjQgMGMxMS42IDAgMjMuMiAxLjMgMzQuNSAzLjlWMTVjLTExLjItMi44LTIyLjgtNC4xLTM0LjUtNC4xLTc5LjcgMC0xNDQuNiA2NC45LTE0NC42IDE0NC42czY0LjkgMTQ0LjYgMTQ0LjYgMTQ0LjZTMzAwIDIzNS4yIDMwMCAxNTUuNWMwLTExLjctMS40LTIzLjMtNC4xLTM0LjVIMzA3YzIuNiAxMS4zIDMuOSAyMi44IDMuOSAzNC41IDAgODUuNi02OS44IDE1NS40LTE1NS41IDE1NS40eiIvPjxwYXRoIGQ9Ik0yNzUuNyAzNS4xVjMuNkgyNTN2MzEuNWgtMzEuNHYyMi43SDI1M3YzMS41aDIyLjdWNTcuOGgzMS41VjM1LjF6Ii8%7CPC9zdmc%7CView%7CExplicit%7CPHN2ZyB2aWV3Qm94PSIwIDAgNDkwLjcgNDkwLjciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI%7CPHBhdGggZD0ibTQ3Mi4zIDIxNi41LTIyNy4xIDIyNy4yLTIyNy4xLTIyNy4yYy00LjItNC4xLTExLTQtMTUuMS4zLTQgNC4xLTQgMTAuNyAwIDE0LjhsMjM0LjcgMjM0LjdjNC4yIDQuMiAxMC45IDQuMiAxNS4xIDBsMjM0LjctMjM0LjdjNC4xLTQuMiA0LTExLS4zLTE1LjEtNC4yLTQtMTAuNy00LTE0LjkgMHoiIGZpbGw9IiM2MDdkOGIiLz48cGF0aCBkPSJtNDcyLjMgMjQuNS0yMjcuMSAyMjcuMi0yMjcuMS0yMjcuMmMtNC4yLTQuMS0xMS00LTE1LjEuMy00IDQuMS00IDEwLjcgMCAxNC44bDIzNC43IDIzNC43YzQuMiA0LjIgMTAuOSA0LjIgMTUuMSAwbDIzNC42LTIzNC43YzQuMi00LjEgNC40LTEwLjguMy0xNS4xLTQuMS00LjItMTAuOC00LjQtMTUuMS0uMy0uMS4yLS4yLjItLjMuM3oiIGZpbGw9IiM2MDdkOGIiLz48cGF0aCBkPSJtMjQ1LjIgNDY5LjRjLTIuOCAwLTUuNS0xLjEtNy42LTMuMWwtMjM0LjYtMjM0LjdjLTQuMS00LjItNC0xMSAuMy0xNS4xIDQuMS00IDEwLjctNCAxNC44IDBsMjI3LjEgMjI3LjEgMjI3LjEtMjI3LjFjNC4yLTQuMSAxMS00IDE1LjEuMyA0IDQuMSA0IDEwLjcgMCAxNC44bC0yMzQuNyAyMzQuN2MtMiAyLTQuNyAzLjEtNy41IDMuMXoiLz48cGF0aCBkPSJtMjQ1LjIgMjc3LjRjLTIuOCAwLTUuNS0xLjEtNy42LTMuMWwtMjM0LjYtMjM0LjdjLTQuMS00LjItNC0xMSAuMy0xNS4xIDQuMS00IDEwLjctNCAxNC44IDBsMjI3LjEgMjI3LjEgMjI3LjEtMjI3LjFjNC4xLTQuMiAxMC44LTQuNCAxNS4xLS4zczQuNCAxMC44LjMgMTUuMWMtLjEuMS0uMi4yLS4zLjNsLTIzNC43IDIzNC43Yy0yIDItNC43IDMuMS03LjUgMy4xeiIvPjwvc3ZnPg%7C1e4%7CscrollHeight%7C5e4%7Cbottom%7Cdo%7CStill%7Cwhile%7CDone%7Cpage%7CWe%7Creached%7Creturn%7Cnew%7CPromise%7CsetTimeout%7CInserting%7CStats%7CCounter%7C26e5f418%7Cbeforebegin%7CWaiting%7C200%7Cvoid%7Cnull%7Chref%7CmoveToElementText%7CcreateRange%7CselectNodeContents%7CremoveAllRanges%7CaddRange%7Cwarn%7CCould%7Ctext%7Cnode%7CUnsupported%7Cbrowser%7CspanUrl%7CTried%7CURL%7Cbecause%7Cevent%7Clistener%7Cbut%7Cdoes%7Cexist%7CRunning%7CPure%7CJavaScript%7CforEach%7CparentNode%7CStarting%7CcreateElement%7Cstyle%7CtextContent%7Chead%7Cappend%7CUn%7Cblur%7Cblurred%7Csource%7Call%7CMake%7Cselectable%7Cfilter%7Cmax%7Cwidth%7Cposition%7CBuy%7CPremium%7Czoom%7CGet%7Caccess%7Carchival%7C299%7C99%7Cmo%7Cpromo%7Cmenu%7Cwe%7Ccan%7Cun%7Chide%7Cadd%7Cpicture%7Cnbutton%7Cspacer%7Cinherit%7Cndiv%7Cmask%7Cwrapper%7Cimpacting%7Chits%7Cany%7Cwhich%7Ccauses%7Caction%7Cauto%7Cwebkit%7Cms%7Cchaining%7Coverscroll%7Cbehavior%7Cunset%7C69882821%7CStops%7Csizes%7Cchanging%7Chappens%7Chit%7CSearch%7Ccause%7Cafter%7Cbefore%7Cbox%7Csizing%7Crevert%7CFormspring%7Cpayment%7Crequest%7CfscCanvas%7Coverlays%7Cblocking%7Cnbody'.split('%7C')%2C0%2C%7B%7D))%7D)()%3B 676 | */ 677 | --------------------------------------------------------------------------------