PlumpAlbert / pornolab inline-torrent preview

// ==UserScript==
// @name         pornolab inline-torrent preview
// @namespace    http://tampermonkey.net/
// @downloadURL https://openuserjs.org/install/PlumpAlbert/pornolab_inline-torrent_preview.min.user.js
// @updateURL https://openuserjs.org/meta/PlumpAlbert/pornolab_inline-torrent_preview.meta.js
// @version      2026-02-21
// @description  Allows to display torrent's poster image as preview on search page instead of category type
// @author       plumpalbert
// @copyright 2026, PlumpAlbert (https://openuserjs.org/users/PlumpAlbert)
// @include      /^https?:\/\/pornolab\.net\/forum\/(tracker|viewforum|viewtopic).*/
// @icon         https://www.google.com/s2/favicons?sz=64&domain=pornolab.net
// @license      MIT
// @run-at       document-end
// ==/UserScript==

const linkClassNames = ["tLink", "tt-text", "torTopic"];

function preloadImage() {
  const links = linkClassNames.flatMap(name => Array.from(document.querySelectorAll(`.${name}`)));
  for (const link of links) {
    let href = link.getAttribute('href');
    if (href.startsWith("./")) {
      href = href.slice(2);
    }
    const url = "https://pornolab.net/forum/" + href;

    const request = new XMLHttpRequest();
    request.open("GET", url, true);
    let oldColor = link.style.color;
    link.style.color = '#BED152';
    request.addEventListener("readystatechange", event => {
      if (request.readyState !== XMLHttpRequest.DONE) {
        return;
      }
      link.style.color = oldColor;

      const imgSrc = new DOMParser().parseFromString(request.responseText, "text/html").querySelector(".postImg").title;
      const img = document.createElement('img');
      img.setAttribute('src', imgSrc);
      img.style.width = '100%';
      img.style.height = '100%';
      img.style.objectFit = 'contain';

      const imageContainerTd = link.parentElement.parentElement.previousElementSibling;
      if (imageContainerTd.tagName === 'TD') {
        imageContainerTd.replaceChildren(img);
      }
    })
    request.send();
  }
}

function isLinkOrContainer(e) {
  let linkNode;
  let nodes = [e.target]
  if (e.target.children.length > 0) {
    nodes = nodes.concat(Array.from(e.target.children));
  }

  for (const name of linkClassNames) {
    for (const node of nodes) {
      if (node.classList.contains(name)) {
        linkNode = node;
        break;
      }
    }
  }

  return linkNode
}

const moreLinkWrappers = ['also-download-topics', 'related-topics']

function reloadPics(e) {
  if (!moreLinkWrappers.some(name => e.target.parentElement.classList.contains(name))) {
    return;
  }

  setTimeout(preloadImage, 2000);
}

window.addEventListener("click", reloadPics);

preloadImage()