plab-ultra

Userscript for PornoLab.Net

< Rückmeldungen auf plab-ultra

Rezension: Gut - Skript funktioniert

§
Veröffentlicht: 01.09.2025

The ultimate PL experience ദ്ദി(˵ •̀ ᴗ - ˵ ) ✧

But I have some requests...


Multi-thumbnail grid

One addition I’d love: place multiple thumbnails/images side-by-side. Because images can already be resized, it’d be super useful to fit more per row (especially for packs with many screenshots).

What: Option to show thumbnails in a row/column grid instead of a single column.

Why: Quickly scan large screenshot packs; better use of horizontal space on wide screens.

Suggestions:

  • Setting: “Thumbnails per row” (1/disable | auto | 2 | 3 | 4 | 5 | 6 …).
  • Optional: small gap control (e.g., 4–16px).
  • Keyboard tweak: [ and ] to decrease/increase columns (optional, but I thought to mention it as you haev several keybinds already).

Renamer script

Sadly, plab-ultra broke my userscript that renamed .torrent files to a specific format [pornolab.net]_ID_Full Title.torrent and after some fussing around I couldn't fix it without editing your code, which I don't really want to do as update could quickly break it.

Although, the tags aren't nescessary in the filename. Maybe as an option, too.


If you implement these, especially the thumbnail grid, I’d be truly grateful.

Thank you! :)

clangmoyaiVerfasser
§
Veröffentlicht: 07.09.2025

Hi! Yeah, I'll add grid settings. About the renamer script, which userscript is that? I could try to make it work for you.

§
Veröffentlicht: 07.09.2025

Yeah, I'll add grid settings.

Glad to hear that!

About the renamer script, which userscript is that? I could try to make it work for you.

It's of my own making. Terrible code and it used tab title, because when I used Pornolab Enhancer's Tags feature I had issues to get the title from website, so I just used tab title and sanitized it.

CODE (click to open)

// ==UserScript==
// @name         PL - Tab title as tor filename (blob enforced)
// @version      1.4
// @author       SH0D4N
// @tag          pornolab
// @tag          pornolab.net
// @description  Force torrent filename from tab title on Pornolab.net (overrides server filename via Blob)
// @match        https://pornolab.net/forum/viewtopic.php?t=*
// @match        https://pornolab.net/forum/viewforum.php?f=*
// @match        https://pornolab.net/forum/tracker.php*
// @grant        none
// @run-at       document-idle
// @namespace    vm-pl-title-filename
// ==/UserScript==

(function () {
  'use strict';

  const SITE_TAG = 'pornolab.net';
  const MAX_FILENAME_CHARS = 240; // safe limit for filename (without path)
  const TORRENT_EXT = '.torrent';

  // Click delegation – also catches dynamically inserted links.
  document.addEventListener('click', async (ev) => {
    const a = ev.target.closest('a');
    if (!a) return;

    if (!isTorrentDownloadLink(a)) return;

    // Respect middle/Ctrl/Shift/Alt/meta – in those cases do nothing
    if (ev.defaultPrevented || ev.button === 1 || ev.metaKey || ev.ctrlKey || ev.shiftKey || ev.altKey) return;

    ev.preventDefault();

    try {
      const url = new URL(a.href, location.href);
      const fileId = url.searchParams.get('t') || url.searchParams.get('id') || '';
      const title = getCleanTitle();
      const base = `[${SITE_TAG}]${fileId ? '_' + fileId : ''}_${title}`;
      const filename = toFilename(base, MAX_FILENAME_CHARS, TORRENT_EXT);

      // Download as Blob, create an object URL, and download with our filename
      const resp = await fetch(url.toString(), { credentials: 'same-origin' });
      if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
      const blob = await resp.blob();

      const blobUrl = URL.createObjectURL(blob);
      triggerDownload(blobUrl, filename);
      URL.revokeObjectURL(blobUrl);
    } catch (e) {
      console.error('[vm-pl-title-filename] Download fallback failed:', e);
      // Fallback: if Blob download fails, let the original behavior happen
      location.href = a.href;
    }
  }, true); // capture=true, so it runs before the page’s handlers

  function isTorrentDownloadLink(a) {
    const href = (a.getAttribute('href') || '').toLowerCase();
    return href.includes('/dl.php') || a.classList.contains('dl-stub');
  }

  function getCleanTitle() {
    // “Tab title” without “ :: PornoLab.Net” at the end
    const clean = document.title.replace(/\s*::\s*PornoLab\.Net\s*$/i, '').trim();
    return clean || 'torrent';
  }

  function toFilename(base, maxChars, ext) {
    let name = sanitizeFilename(base);

    // remove duplicate extension
    if (name.toLowerCase().endsWith(ext)) {
      name = name.slice(0, -ext.length);
    }

    // shorten so it fits with extension
    const maxBase = Math.max(1, maxChars - ext.length);
    if (name.length > maxBase) {
      name = name.slice(0, maxBase).replace(/[.\s]+$/g, '');
    }
    return name + ext;
  }

  function sanitizeFilename(input) {
    // normalize whitespace
    let s = input.replace(/\s+/g, ' ').trim();

    // forbidden characters in Windows
    s = s.replace(/[\\/:*?"<>|]/g, '-').replace(/[\x00-\x1F\x7F]/g, '');

    // avoid reserved device names
    s = s.split(/([._\s-]+)/).map((part, i) => (i % 2 ? part : avoidReserved(part))).join('');

    // remove trailing dots/spaces
    s = s.replace(/[.\s]+$/g, '');
    return s || 'torrent';
  }

  function avoidReserved(stem) {
    const res = new Set([
      'CON','PRN','AUX','NUL',
      'COM1','COM2','COM3','COM4','COM5','COM6','COM7','COM8','COM9',
      'LPT1','LPT2','LPT3','LPT4','LPT5','LPT6','LPT7','LPT8','LPT9'
    ]);
    return res.has(stem.toUpperCase()) ? stem + '-' : stem;
  }

  function triggerDownload(href, filename) {
    const a = document.createElement('a');
    a.href = href;
    a.download = filename; // force filename thanks to blob: URL
    a.style.display = 'none';
    document.body.appendChild(a);
    a.click();
    a.remove();
  }
})();

```
clangmoyaiVerfasser
§
Veröffentlicht: 17.09.2025

okay, I've added columns settings to top-right in images section

also added id to dl link, so you can do something like this

const title = document.title;
const prefix = "[pornolab.net]";

const element = document.getElementById("dl-link");
const href = element?.href;
const url = new URL(href, location.href);
const id = url.searchParams.get("t");

const button = element?.parentElement;
if (button) {
  button.addEventListener(
    "click",
    (event) => {
      event.stopImmediatePropagation();
      event.preventDefault();

      console.log(`${prefix}_${id}_${title}`);
    },
    true
  );
}

console.log({
  title,
  id,
  prefix,
});
§
Veröffentlicht: 18.09.2025

okay, I've added columns settings to top-right in images section

It looks really great and functions just as good!

also added id to dl link, so you can do something like this

The tags doesn't seems to be in the filename, but no worries. Title is good enough. Thanks.

Antwort schreiben

Anmelden um eine Antwort zu senden.