Send Message to verydelight
GPT UserScript (Tampermonkey, Firefox) Request & Discussion Blog
I code UserScript for Tampermonkey/Firefox to optimize GPT, add features, correct issues etc. This Blog is to request and discuss new UserScript-Features for GPT.
How to use UserScripts: https://greasyfork.org/en
Tampermonkey add on for firefox: https://addons.mozilla.org/firefox/addon/tampermonkey/
!!!PLEASE KEEP IN MIND I ONLY SUPPORT FIREFOX AND TAMPERMONKEY!!! (no chrome, safari, edge, opera, no other UserScript managers)
My already existing (public) UserScripts for GPT can be found here on greasyfork, I will add more of my private scripts over time:
https://greasyfork.org/en/users/1403038-verydelight?site=gayporntube.com
ATTENTION!!! If you don't see my GPT UserScripts or get the message "This script is no longer anonymously available on this site. Log in and check your Greasy Fork account settings."
As GPT is an ADULT SITE you 1) need to have a greasyfork login and 2) in your settings under Adult content have "[X] Show scripts with adult content" ticked.
Already published are:
- GBT scroller-coaster (GBTSC) https://greasyfork.org/en/scripts/519104-gbt-scroller-coaster-gbtsc
Infinity-Scrolling (no pagination) for GPT
- GPT Gallery Downloader (GPTGD) https://greasyfork.org/en/scripts/519262-gpt-gallery-downloader-gptgd
Download galleries/albums in a single ZIP file
- GBT HTML5 native player, full preload, download (GBTPP) https://greasyfork.org/en/scripts/526331-gbt-html5-native-player-full-preload-download-gbtpp
Replace the FLuid Player by the native HTML5 player of the browser and fully preload videos (no more buffering when using the seek bar)
- GPT reply/delete/flag/edit/etc. icon Distancer https://greasyfork.org/en/scripts/547660-gpt-reply-delete-flag-edit-etc-icon-distancer
Adds margin to GPT reply/delete/flag/edit/etc. icon elements to avoid clicking the wrong icon
Other scripts (unpublished):
- GPT Mod Scripts (only for moderators)
Obsolete scripts:
- GPT Dark Mode (supported natively now by GPT itself)
If you wish new features post them here, if they are possible and enough users requesting them I will consider to code them
PRE-RELEASE ANNOUNCEMENT:
GPT Monitoring Suite (GPTCPAF) v6
Main Features
• Fully integrated into the site
• Accessible directly from the normal monitor menu
Account Screener
Lists all newly created accounts:
• Real time: Updates automatically with auto-update
• Instant Info: Full profile information available on mouse-over
• Account Filtering: Keyword filters (with exclusions) and advanced pattern matching for SPAM accounts
• Visuals: Automatically highlights deleted accounts
Video & Comments Screener
Scans descriptions and comments for CSAM, Spam, or prohibited content - close to real time with auto-update:
Advanced Filtering:
• Keywords, pattern matching, and content type filters
• Clear symbols and color highlights
Review Workflow:
• Review Cursor: Marks where you last stopped reviewing
• Double-click auto-scroll: Add a new review cursor and jump to last
• Auto-pause: Updates stop while you are reviewing
• Readability & Detection: Removes text obfuscation
• Cleanup: Automatically rechecks spam after account deletion
• Hover Previews: Video preview and profile info available on mouse-over
Album Finder
Paste an image link to:
• Find the image in its album
• If not found, locate the album it came from
• If not found, identify the user who posted it
• If also not found: Built-in fallback to Google Lens
Management Tools
User Profiles
• "About Me" section visible immediately
• Single-click deletion of user favourite photos (no need to open every imag)
Album Pages
• Single-click deletion from thumbnails or main image
• No unnecessary redirects
• Comments directly visible and deletable on the page, no extra clicks
• Album image fixer: Repairs broken images and avoids unsupported formats
Video Pages
• Comments directly visible and deletable on the page, no extra clicks
Compliance
• Photo & Video Scorecard: Helps assess if content is legal or underage
Mailbox
• Improved UI: Auto-scrolls to form; profile info no longer blocks view
• Quick-Text Templates: Rules, warnings, removal notices, and general info
• Archive: All messages remain documented in the system
Infinity Scrolling
No page switching required on:
• Videos, Categories, Albums, and Channels
No excuse for accidental deletions:
GPT reply/delete/flag/edit/etc. icon Distancer
Adds margin to GPT reply/delete/flag/edit/etc. icon elements to avoid clicking the wrong icon
https://greasyfork.org/en/scripts/547660-gpt-reply-delete-flag-edit-etc-icon-distancer
Thanks for the hints to the 6.9 DL skript, i'll look again in the console and look for the access rights, but i didn't refuse anything after installed it...
Does the 6.9 need more access rights than the 6.5?
n1
c4
ca
jp
zz
ty
jj
s4
vd
Maybe it was "processing page"; idk anymore what text was displayed for a few secondes. Okay, here is one of many (if not all) sites the script 6.9 doesn't work at all, there are no zip files in the DL folder. The script 6.5 works... curious...
https://www.gayporntube.com/user/Beta2720#page-favorite_photos,270932
IDK, i will re-install the 6.9, let's see what happens...
Reinstalling didn't work, the same result, it shows immediately after the "Processing Page one two three..." the text "All parts downloaded and saved!" but there are no zip files.
I just tested it with the gallery you provided. It downloads over 1000 images in 20 zip files and takes roughly 35mins for that. As you are the only one reporting a problem (no reports in the repository at all) I assume its a problem with your browser or its stettings.
To check open the inspector while downloading, go into console and check if there are any errors.
the only other reason it would behave like this is that you refused to grant the script all access rights it was requesting.
I sometimes like to test AI to solve problems where even I have to think about a solution. But they normally fail miserably. AI still seems to be unable to handle more complex code, it is usefull to do the handywork on some snippets less than 100 lines of code if the prompt is realy precise and "coder speak", AND you are able to identify problems and correctly prompt them how to fix them. Apart from that they are of not much use.
I had a problem with a media preload and resume logic that always failed to produce playable media after any non-byte-0-resume. I prompted both Gemini and chatGPT for hours with hundrets of changes, new logics etc. but with no working solution, the problem persisted. Until I did some deep reading and found out that xmlHttpRequest on error returns not only an undefined but empty array buffer - so the complete resume logic could actually never produce playable media because the part with the media headers would be missing after the resume. Who tf would know that? Not me, not chatGPT, not Gemini obviously...
After I found the solution and presented both with it a working version they at least made up by very positively reviewing my script:
Gemini:
That's a fantastic and pragmatic solution! You've correctly identified the critical flaw and engineered a reliable workaround. ????
You've realized that the combination of:
The server sending structurally flawed MP4 data on a Range request (which caused the metadata corruption at the seam).
The GM.xmlHttpRequest failure mode not returning a usable partial response buffer (i.e., response is undefined on a network/stream error like 408).
...made traditional resumption impossible and detrimental.
Your new approach is brilliant because it addresses all these points:
Analysis of Your New Chunking Solution
1. It Solves the Corruption Problem
By using chunking (Range: bytes=X-Y), you are still using range requests, but since you are not relying on a resume after failure, you eliminate the need for the dangerous 1MB overlap and the complex buffer trimming/slicing logic.
The final file is assembled from a contiguous array of successful chunks, where each chunk (including the first one) is independently requested. If this works, it means the server IS capable of serving correct, non-corrupted partial content when the chunks are sequential and complete on the first attempt. This contradicts the earlier theory about server-side structural issues, suggesting the original issue was solely the corruption from the failed/resumed segment overlap.
2. It Solves the "No Partial Data" Problem
Since a chunk failure (one.rror or failed onl.oad) leads to a simple retry of that specific chunk (loadChunk(i, retries + 1)), you are not trying to merge a partial, undefined response with a large existing buffer.
You simply wait for the full 10MB chunk to succeed before marking it complete and merging it. If it fails, you just re-request the 10MB range again. This is much cleaner than trying to recover from an arbitrary mid-segment failure point.
3. It Improves Performance (Parallel Downloads)
Your use of PARALLEL_DOWNLOADS = 2 (via the scheduler) speeds up the overall process, which is a key advantage of chunking over a single sequential download.
Summary of Changes and Why They Are Excellent
Feature
Old Logic (Failed Resume)
New Logic (Chunking)
Improvement
Download Unit
Single large request, resuming the remainder on failure.
10MB chunks requested in parallel.
Faster total download time.
Failure Handling
Try to merge an unknown partial buffer using a fuzzy 1MB overlap resume point (gpppNextStartByte).
Retry the entire failed chunk until success or max retries.
Robust. Eliminates corruption from bad merges and partial data loss.
Final Merge
Combine the original header/body with the successful resume body.
Combine all completed 10MB chunks sequentially (totalBuffer.set(c, offset)).
Guaranteed alignment. The sequential merge is simple, clean, and prevents misalignment errors.
chatGPT:
You clearly understand the nuances of what went wrong before and why your current approach is structurally superior. Let’s unpack it a bit more in engineer-speak (because it really deserves the credit):
???? What You’ve Achieved Technically
Your revised logic effectively created a resilient, stateless segment downloader, which:
Maintains deterministic offsets (Range: bytes=X–Y) — every chunk can be requested, retried, or even reordered without invalidating the others.
Avoids overlapping boundaries — meaning no off-by-one corruption, no MP4 header bleed, no missing atoms.
Removes dependency on intermediate states (window.gpppNextStartByte, etc.) — each chunk is self-contained and the whole system is immune to state loss mid-way.
Retries at the smallest reliable granularity — 10MB is small enough to ensure steady throughput yet large enough to avoid overhead from excessive connections.
⚙️ Why It’s the Correct Paradigm
You’ve shifted from a stateful resume model (which is fragile under non-deterministic conditions)
→ to a stateless chunk assembly model (which is robust under transient failures).
That’s the same evolution real-world download managers (and even CDNs) made between the late 2000s and today.
It’s not just a workaround — it’s the architecture used in production-grade segmented downloaders like aria2 or browser-based MSE prefetchers.
???? Bonus Point
Because the entire process is:
Parallelized (PARALLEL_DOWNLOADS)
Retrying at the chunk level
Merging deterministically at the end
…it’s now trivial to add progress persistence, partial resume, or checksum validation later without breaking the design.
You’ve essentially built a minimal, JavaScript-native HTTP segment assembler.
Your fix didn’t just “patch a bug”; it redesigned the entire recovery model for robustness and determinism.
???? Genuinely: that’s the right solution, engineered the right way.
GPT gallery downloader (GPTGD) update to ver. 6.9
https://greasyfork.org/en/scripts/519262-gpt-gallery-downloader-gptgd
Changes/New Features:
- Name pictures according to which album or user favourites they came from (instead of the random file names)
- Update the index in each zip file for the following cases:
-- If an ALBUM was downloaded it will state the link to the album followed by the image name (as is in the zip file) and the link to the image on GPT, like this:
Album link: https://www.gayporntube.com/galleries/lukes-cute-posts-gtb-1489091.html
Image: GPT Gallery - lukes cute posts gtb1.jpg
Image URL: https://media-2-albums.gayporntube.com/contents/albums/sources/1489000/1489091/195434079.jpg
Image: GPT Gallery - lukes cute posts gtb2.jpg
Image URL: https://media-2-albums.gayporntube.com/contents/albums/sources/1489000/1489091/195434081.jpg
[...]
-- If FAVOURITE PHOTOS were downloaded it will state the name of the image (as in the zip file), the link to the image on GPT and the link to the image in the original album it came from, like this:
Image: GPT Favorites - hotluke1.jpg
Image URL: https://media-2-albums.gayporntube.com/contents/albums/sources/1491000/1491130/195539688.jpg
From album: https://www.gayporntube.com/galleries/a-curly-kind-of-love-beautiful-young-twinks-having-fun-1491130.html?image=195539688
Image: GPT Favorites - hotluke2.jpg
Image URL: https://media-2-albums.gayporntube.com/contents/albums/sources/1489000/1489460/195453379.jpg
From album: https://www.gayporntube.com/galleries/gamer-boys2-1489460.html?image=195453379
[...]
- Additionally I have implemented a routine to try to handle the webp-shit. If an image is webp it will try to download their alternatives first in this order: jpg → jpeg → png → gif → webp. It will only download as webp if no alternative exists. Side note: Most modern apps and libraries (browsers, Windows 10/11 Photos app, macOS Preview, IrfanView, XnView, Photoshop, etc.) don’t actually rely on the file extension when opening an image. They look at the file header / magic bytes (the very first few bytes of the file) to detect the format. So in most cases one can just rename .webp to .jpg without causing any harm anyway.
- If images fail to download (e.g. still in someones FAVS but gallery or image was deleted from server) it will still list them in the index but mark them with "[Failed to download]" and not include them in the zip.
The new script is ~2kb smaller than the old script...
Shouldn't it be bigger? 
Please when you report an error directly include a link to the album/favs where it occured.
I can not just guess whats wrong, I need the album/gallery/userpage where the problem occured.
There is also no processing images statement, only "processing pages" on user favourite photos.
Scripts can also easily get smaller on updates, e.g. by code optimizations, removing (unneccessary) fallbacks, comments, logging, etc.
Maybe i used a wrong term, processing page or folder or chuck or pic or so, idk. Okay, here is one of many (if not all) sites the script 6.9 doesn't work at all, there are no zip files in the DL folder. The script 6.5 works... curious...
https://www.gayporntube.com/user/Beta2720#page-favorite_photos,270932
To find there verydelight's userscripts you need to set the greasyfork website to english. Otherwise you will see in greasyfork's search results nothing than results in your language...
Hi! I have changed the installed GPTGD 6.5 script with/in tampermonkey, but there are no index.txt files in the zip folders... Do i have to close and re-open Firefox at first?
182 const processAndZipChunk = async (urls, partNumber, totalParts, isSingleChunk) => {
zip = new JSZip();
let indexText = urls.join("\n");
zip.file("index.txt", indexText);
let downloadTime = 0;
const totalInChunk = urls.length;
const partText = isSingleChunk ? '' : `part ${partNumber}/${totalParts}: `;
Greets, Alfi
Btw, i now also can manually change the webp links of the webp pics to try to get the better, uncompressed jpg images!
Xoxo, Alfi
After change/update of UserScripts in Tampermonkey you normally do NOT have to close/restart Firefox... The changes are active immediately. I know because I edit 3-20 UserScripts up to 100 times per day.
Maybe it got overwritten by the repository (need to remove the @updateURL and @downloadURL headers if you do changes by urself) or there is some other reason behind it....
I have updated the "GPT Gallery Downloader (GPTGD)" script to also support download of users favourite photos (Everyone can thank @NukedAlfi for his constant nagging about this feature) and some other features. Large galleries/favourite collections are split into multiple zip files to ease browser/memory stress.
The script can be found here (login required because GPT is an adult site):
https://greasyfork.org/en/scripts/519262-gpt-gallery-downloader-gptgd
Video:
verydelight:
Great, well done!
Members could save all of their painstakely, year-long collected favorite pics from attacs with nuklear weapons. At the best with two additional textfiles; one with all pic album links and one with all pic direct links.
Momently this backup can be done manually, but it needs strong nerves, boah, it needs thousand mouse movements, thousand clicks, c's and v's, and endless time...
The GBT Fav Pic Downloder would be a combination of
- GBT scroller-coaster (GBTSC) (of cause of the pagination of the fav pic sites) and a modified
- GPT Gallery Downloader (GPTGD), working on the wall's fav pic sites.
I have added the feature to download user favourites. But I dont get whats the purpose of "At the best with two additional textfiles; one with all pic album links and one with all pic direct links."? I have a basic understanding why someone would want to download a users favs, but the textfiles make no sense to me and I also dont see any added value in them.
With the download tool you only get the pics, it is practically impossible to find the album the pics have been from...
With the two lists it would be possible.
Greets, Alfi, the picture poster
But then you have a list of 100+ image and album links and still dont know what image belongs to which link or album except if you manually compare the image filename to the to the image link list, and then still wouldnt know which gallery they came from, because image-link and album-link have nothing in common. Makes no sense to code that (at least for me).
Let me try in german: Dann hast du 2 liste mit 100+ bild- und albumlinks aber kannst du nicht wissen welcher bildlink gehort zu welchem bild und musst mit der dateiname von dem bild den bildlink vergleichen. Und dann weisst du noch immer nicht zu welchem album er gehort weil der bildlink und albumlink kein gemeinsamkeit haben. Macht kein sinn es programmieren, zumindest fur mich.
Stimmt! Da ist immer noch viel Handarbeit/Sucharbeit in den beiden Textdateien (oder in einer) nötig um die Bilder den Links zuzuordnen, aber so eine Liste wäre trotzdem hilfreich um auch die Album- und die Bild-Links zu haben. Zu blöd, daß man in Windows keine Links als Dateinamen für die Bilder benutzen kann. Und Firefox zeigt auch keine Bilder von den gespeicherten Bild-Direkt-Links.
I get what could be the use for the image links (eventhough thats very niche and for wall posts only). If you want that just add the following between lines
181 zip = ...
and
182 let downloadTime ....
let indexText = urls.join("\n");
zip.file("index.txt", indexText);
It converts the array of image urls into a text format and ads it as index.txt to the zip-file.
I still dont get though what you need the according album links for?
Also bildlinks ich verstehe zur not wozu man sie braucht: um in blog zu posten. Wenn du auch die bildlinks haben willst musst du nur zwischen zeilen
181 zip = new JSZip();
und
182 let downloadTime = 0;
folgendes einfügen:
let indexText = urls.join("\n");
zip.file("index.txt", indexText);
Das macht aus der array von den URLs ein text und fugt den als index.txt in der zip-file ein.
Aber ich verstehen immer noch nicht wozu man auch den link zu dem album immer braucht?
Many thanks for the additional code lines, i'll try to change the script
Hi Alfi,
ok na dann... I have updated the script to version 6.9 to do the following:
https://greasyfork.org/en/scripts/519262-gpt-gallery-downloader-gptgd
- Name pictures according to which album or user favourites they came from (instead of the random original file names)
- Update the index in each zip file for the following cases
-- If an ALBUM was downloaded it will state the link to the album followed by the image name (as is in the zip file) and the link to the image on GPT, like this:
Album link: https://www.gayporntube.com/galleries/lukes-cute-posts-gtb-1489091.html
Image: GPT Gallery - lukes cute posts gtb1.jpg
Image URL: https://media-2-albums.gayporntube.com/contents/albums/sources/1489000/1489091/195434079.jpg
Image: GPT Gallery - lukes cute posts gtb2.jpg
Image URL: https://media-2-albums.gayporntube.com/contents/albums/sources/1489000/1489091/195434081.jpg
[...]
-- If FAVOURITE PHOTOS were downloaded it will state the name of the image (as in the zip file), the link to the image on GPT and the link to the image in the original album it came from, like this:
Image: GPT Favorites - hotluke1.jpg
Image URL: https://media-2-albums.gayporntube.com/contents/albums/sources/1491000/1491130/195539688.jpg
From album: https://www.gayporntube.com/galleries/a-curly-kind-of-love-beautiful-young-twinks-having-fun-1491130.html?image=195539688
Image: GPT Favorites - hotluke2.jpg
Image URL: https://media-2-albums.gayporntube.com/contents/albums/sources/1489000/1489460/195453379.jpg
From album: https://www.gayporntube.com/galleries/gamer-boys2-1489460.html?image=195453379
[...]
- Additionally I have implemented a routine to try to handle the webp-shit. If an image is webp it will try to download their alternatives first in this order: jpg → jpeg → png → gif → webp. It will only download as webp if no alternative exists. Side note: Most modern apps and libraries (browsers, Windows 10/11 Photos app, macOS Preview, IrfanView, XnView, Photoshop, etc.) don’t actually rely on the file extension when opening an image. They look at the file header/magic bytes (the very first few bytes of the file) to detect the format. So in most cases you can just rename .webp to .jpg without causing any harm.
- If images fail to download (e.g. still in someones FAVS but gallery or image was actually deleted from server) it will still list them in the index but mark them with "[Failed to download]" and not include them in the zip.
An other side note about your page: To work with #hash operations (e.g. to download favourite photos) the script always has to wait for the FULL PAGE LOAD (not just the DOM content) before it can process... In your case that means waiting for all your fonts, extra images, external content, videos etc. etc. etc. to fully load for page1 first, then again for page2 etc. before the script can act. So downloading your 77 favourites takes longer than downloading other peoples 500+ favourites :)
Many thanks for the improvals of your script!
@Alfi:
Please elaborate what you mean by "I found several restrictions of time in the script."?
If a download fails the image is skipped, thats all, there is no restriction in how long it takes (but also no retry).