PornXnow Video Downloader

Download videos from pornxnow.me with one click

Size

9.7 KB

Version

1.0.1

Created

Jan 10, 2026

Updated

11 days ago

1// ==UserScript==
2// @name		PornXnow Video Downloader
3// @description		Download videos from pornxnow.me with one click
4// @version		1.0.1
5// @match		https://*.pornxnow.me/*
6// @icon		https://pornxnow.me/wp-content/uploads/2019/05/cropped-favicon-pornxnow-32x32.png
7// @grant		GM.xmlhttpRequest
8// @connect		pxnw.xyz
9// @connect		*.pxnw.xyz
10// ==/UserScript==
11(function() {
12    'use strict';
13
14    console.log('PornXnow Video Downloader initialized');
15
16    // Debounce function to prevent multiple rapid calls
17    function debounce(func, wait) {
18        let timeout;
19        return function executedFunction(...args) {
20            const later = () => {
21                clearTimeout(timeout);
22                func(...args);
23            };
24            clearTimeout(timeout);
25            timeout = setTimeout(later, wait);
26        };
27    }
28
29    // Function to extract video URL from iframe
30    async function extractVideoUrl(iframeSrc) {
31        try {
32            console.log('Fetching iframe content from:', iframeSrc);
33            
34            return new Promise((resolve, reject) => {
35                GM.xmlhttpRequest({
36                    method: 'GET',
37                    url: iframeSrc,
38                    headers: {
39                        'Referer': window.location.href,
40                        'User-Agent': navigator.userAgent
41                    },
42                    onload: function(response) {
43                        TM_log('Response status:', response.status);
44                        TM_log('Response received, length:', response.responseText ? response.responseText.length : 0);
45                        
46                        const html = response.responseText;
47                        TM_log('HTML content preview (first 1000 chars):', html ? html.substring(0, 1000) : 'NO HTML');
48
49                        // Try to find video URL in various formats
50                        let videoUrl = null;
51
52                        // Method 1: Look for direct video sources
53                        const videoSourceMatch = html.match(/sources:\s*\[\s*{[^}]*file:\s*["']([^"']+\.mp4[^"']*)["']/i);
54                        if (videoSourceMatch) {
55                            videoUrl = videoSourceMatch[1];
56                        }
57
58                        // Method 2: Look for file: property
59                        if (!videoUrl) {
60                            const fileMatch = html.match(/file:\s*["']([^"']+\.mp4[^"']*)["']/i);
61                            if (fileMatch) {
62                                videoUrl = fileMatch[1];
63                            }
64                        }
65
66                        // Method 3: Look for video tag src
67                        if (!videoUrl) {
68                            const videoTagMatch = html.match(/<video[^>]+src=["']([^"']+)["']/i);
69                            if (videoTagMatch) {
70                                videoUrl = videoTagMatch[1];
71                            }
72                        }
73
74                        // Method 4: Look for any .mp4 URL
75                        if (!videoUrl) {
76                            const mp4Match = html.match(/(https?:\/\/[^"'\s]+\.mp4[^"'\s]*)/i);
77                            if (mp4Match) {
78                                videoUrl = mp4Match[1];
79                            }
80                        }
81
82                        if (videoUrl) {
83                            // Clean up the URL
84                            videoUrl = videoUrl.replace(/\\/g, '');
85                            console.log('Video URL found:', videoUrl);
86                            resolve(videoUrl);
87                        } else {
88                            console.error('Could not find video URL in iframe content');
89                            console.log('HTML preview:', html.substring(0, 500));
90                            reject(new Error('Could not find video URL in iframe content'));
91                        }
92                    },
93                    onerror: function(error) {
94                        console.error('GM.xmlhttpRequest error:', error);
95                        reject(new Error('Failed to fetch iframe content: ' + (error.error || 'Network error')));
96                    },
97                    ontimeout: function() {
98                        console.error('Request timed out');
99                        reject(new Error('Request timed out'));
100                    }
101                });
102            });
103        } catch (error) {
104            console.error('Error extracting video URL:', error);
105            throw error;
106        }
107    }
108
109    // Function to create download button
110    function createDownloadButton() {
111        console.log('Creating download button');
112
113        // Find the video player container
114        const videoWrapper = document.querySelector('.video-wrapper');
115        if (!videoWrapper) {
116            console.error('Video wrapper not found');
117            return;
118        }
119
120        // Check if button already exists
121        if (document.getElementById('custom-video-downloader')) {
122            console.log('Download button already exists');
123            return;
124        }
125
126        // Create download button container
127        const downloadContainer = document.createElement('div');
128        downloadContainer.id = 'custom-video-downloader';
129        downloadContainer.style.cssText = `
130            margin: 15px 0;
131            padding: 15px;
132            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
133            border-radius: 8px;
134            text-align: center;
135            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
136        `;
137
138        // Create download button
139        const downloadButton = document.createElement('button');
140        downloadButton.id = 'download-video-btn';
141        downloadButton.innerHTML = '<i class="fa fa-download"></i> Download Video (HD)';
142        downloadButton.style.cssText = `
143            background: #fff;
144            color: #667eea;
145            border: none;
146            padding: 12px 30px;
147            font-size: 16px;
148            font-weight: bold;
149            border-radius: 5px;
150            cursor: pointer;
151            transition: all 0.3s ease;
152            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
153        `;
154
155        downloadButton.onmouseover = function() {
156            this.style.transform = 'scale(1.05)';
157            this.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.3)';
158        };
159
160        downloadButton.onmouseout = function() {
161            this.style.transform = 'scale(1)';
162            this.style.boxShadow = '0 2px 4px rgba(0, 0, 0, 0.2)';
163        };
164
165        downloadButton.onclick = async function() {
166            const originalText = this.innerHTML;
167            this.innerHTML = '<i class="fa fa-spinner fa-spin"></i> Extracting video...';
168            this.disabled = true;
169
170            try {
171                // Get iframe source
172                const iframe = document.querySelector('.responsive-player iframe');
173                if (!iframe || !iframe.src) {
174                    throw new Error('Video iframe not found');
175                }
176
177                const videoUrl = await extractVideoUrl(iframe.src);
178                
179                if (videoUrl) {
180                    this.innerHTML = '<i class="fa fa-check"></i> Opening download...';
181                    
182                    // Open video in new tab for download
183                    GM.openInTab(videoUrl, false);
184                    
185                    setTimeout(() => {
186                        this.innerHTML = originalText;
187                        this.disabled = false;
188                    }, 2000);
189                } else {
190                    throw new Error('Could not extract video URL');
191                }
192            } catch (error) {
193                console.error('Download error:', error);
194                console.error('Error message:', error.message);
195                console.error('Error stack:', error.stack);
196                this.innerHTML = '<i class="fa fa-exclamation-triangle"></i> Error - Try again';
197                this.style.background = '#ff6b6b';
198                this.style.color = '#fff';
199                
200                setTimeout(() => {
201                    this.innerHTML = originalText;
202                    this.style.background = '#fff';
203                    this.style.color = '#667eea';
204                    this.disabled = false;
205                }, 3000);
206            }
207        };
208
209        downloadContainer.appendChild(downloadButton);
210
211        // Insert after video player
212        const videoPlayer = videoWrapper.querySelector('.responsive-player');
213        if (videoPlayer && videoPlayer.nextSibling) {
214            videoWrapper.insertBefore(downloadContainer, videoPlayer.nextSibling);
215        } else {
216            videoWrapper.appendChild(downloadContainer);
217        }
218
219        console.log('Download button created successfully');
220    }
221
222    // Initialize the extension
223    function init() {
224        console.log('Initializing video downloader');
225
226        // Wait for page to load
227        if (document.readyState === 'loading') {
228            document.addEventListener('DOMContentLoaded', init);
229            return;
230        }
231
232        // Check if we're on a video page
233        const videoWrapper = document.querySelector('.video-wrapper');
234        if (!videoWrapper) {
235            console.log('Not a video page, extension will not run');
236            return;
237        }
238
239        // Wait a bit for iframe to load
240        setTimeout(() => {
241            createDownloadButton();
242        }, 2000);
243
244        // Observe DOM changes in case content loads dynamically
245        const observer = new MutationObserver(debounce(() => {
246            if (!document.getElementById('custom-video-downloader')) {
247                createDownloadButton();
248            }
249        }, 1000));
250
251        observer.observe(document.body, {
252            childList: true,
253            subtree: true
254        });
255    }
256
257    // Start the extension
258    init();
259})();
PornXnow Video Downloader | Robomonkey