Video Downloader for PornforUs

Download videos from PornforUs with one click

Size

8.8 KB

Version

1.0.1

Created

Jan 31, 2026

Updated

4 days ago

1// ==UserScript==
2// @name		Video Downloader for PornforUs
3// @description		Download videos from PornforUs with one click
4// @version		1.0.1
5// @match		https://*.pornforus.com/*
6// @icon		https://www.pornforus.com/favicon.ico
7// ==/UserScript==
8(function() {
9    'use strict';
10
11    console.log('Video Downloader extension loaded');
12
13    // Add custom styles for the download button
14    TM_addStyle(`
15        .video-download-btn {
16            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
17            color: white;
18            padding: 12px 24px;
19            border-radius: 8px;
20            font-weight: bold;
21            cursor: pointer;
22            border: none;
23            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
24            transition: all 0.3s ease;
25            display: inline-flex;
26            align-items: center;
27            gap: 8px;
28            font-size: 16px;
29            margin-top: 16px;
30        }
31        
32        .video-download-btn:hover {
33            transform: translateY(-2px);
34            box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
35            background: linear-gradient(135deg, #764ba2 0%, #667eea 100%);
36        }
37        
38        .video-download-btn:active {
39            transform: translateY(0);
40        }
41        
42        .video-download-btn:disabled {
43            opacity: 0.6;
44            cursor: not-allowed;
45            transform: none;
46        }
47        
48        .download-status {
49            margin-top: 8px;
50            padding: 8px 12px;
51            border-radius: 6px;
52            font-size: 14px;
53            display: none;
54        }
55        
56        .download-status.success {
57            background: #d4edda;
58            color: #155724;
59            display: block;
60        }
61        
62        .download-status.error {
63            background: #f8d7da;
64            color: #721c24;
65            display: block;
66        }
67        
68        .download-status.info {
69            background: #d1ecf1;
70            color: #0c5460;
71            display: block;
72        }
73    `);
74
75    async function extractVideoUrl(iframeSrc) {
76        try {
77            console.log('Extracting video URL from:', iframeSrc);
78            
79            // Extract the video ID from the iframe URL
80            const videoIdMatch = iframeSrc.match(/embed\/\d+\/([a-f0-9-]+)/);
81            if (!videoIdMatch) {
82                throw new Error('Could not extract video ID');
83            }
84            
85            const videoId = videoIdMatch[1];
86            console.log('Video ID:', videoId);
87            
88            // Construct the direct video URL (Bunny CDN format)
89            const videoUrl = `https://iframe.mediadelivery.net/play/383660/${videoId}`;
90            
91            return videoUrl;
92        } catch (error) {
93            console.error('Error extracting video URL:', error);
94            throw error;
95        }
96    }
97
98    async function downloadVideo(videoUrl, filename) {
99        try {
100            console.log('Downloading video from:', videoUrl);
101            
102            // Use GM.xmlhttpRequest to fetch the video with proper headers
103            const response = await GM.xmlhttpRequest({
104                method: 'GET',
105                url: videoUrl,
106                responseType: 'blob',
107                headers: {
108                    'Referer': window.location.href,
109                    'Origin': window.location.origin
110                }
111            });
112            
113            console.log('Video fetched, creating download link');
114            
115            // Create a blob URL and trigger download
116            const blob = response.response;
117            const blobUrl = URL.createObjectURL(blob);
118            
119            const a = document.createElement('a');
120            a.href = blobUrl;
121            a.download = filename;
122            document.body.appendChild(a);
123            a.click();
124            document.body.removeChild(a);
125            
126            // Clean up the blob URL after a delay
127            setTimeout(() => URL.revokeObjectURL(blobUrl), 100);
128            
129            console.log('Download initiated successfully');
130            return true;
131        } catch (error) {
132            console.error('Error downloading video:', error);
133            throw error;
134        }
135    }
136
137    function createDownloadButton() {
138        console.log('Creating download button');
139        
140        // Find the video title container
141        const titleContainer = document.querySelector('.text-2xl.sm\\:text-3xl.font-bold.mb-4');
142        if (!titleContainer) {
143            console.error('Could not find title container');
144            return;
145        }
146        
147        const videoTitle = titleContainer.textContent.trim();
148        console.log('Video title:', videoTitle);
149        
150        // Create download button container
151        const buttonContainer = document.createElement('div');
152        buttonContainer.style.cssText = 'margin-top: 16px;';
153        
154        // Create download button
155        const downloadBtn = document.createElement('button');
156        downloadBtn.className = 'video-download-btn';
157        downloadBtn.innerHTML = `
158            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
159                <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
160                <polyline points="7 10 12 15 17 10"></polyline>
161                <line x1="12" y1="15" x2="12" y2="3"></line>
162            </svg>
163            Download Video
164        `;
165        
166        // Create status message element
167        const statusMsg = document.createElement('div');
168        statusMsg.className = 'download-status';
169        
170        buttonContainer.appendChild(downloadBtn);
171        buttonContainer.appendChild(statusMsg);
172        
173        // Insert after the title
174        titleContainer.parentElement.insertBefore(buttonContainer, titleContainer.nextSibling);
175        
176        // Add click handler
177        downloadBtn.addEventListener('click', async () => {
178            try {
179                downloadBtn.disabled = true;
180                downloadBtn.textContent = 'Preparing download...';
181                statusMsg.className = 'download-status info';
182                statusMsg.textContent = 'Extracting video URL...';
183                
184                // Get iframe source
185                const iframe = document.querySelector('iframe');
186                if (!iframe || !iframe.src) {
187                    throw new Error('Video iframe not found');
188                }
189                
190                const videoUrl = await extractVideoUrl(iframe.src);
191                
192                statusMsg.textContent = 'Starting download...';
193                
194                // Generate filename from video title
195                const filename = videoTitle.replace(/[^a-z0-9]/gi, '_').toLowerCase() + '.mp4';
196                
197                // Try to open the video URL in a new tab as a fallback
198                // This allows the user to download it manually if direct download fails
199                GM.openInTab(videoUrl, false);
200                
201                statusMsg.className = 'download-status success';
202                statusMsg.textContent = 'Video opened in new tab! Right-click and select "Save video as..." to download.';
203                
204                downloadBtn.disabled = false;
205                downloadBtn.innerHTML = `
206                    <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
207                        <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
208                        <polyline points="7 10 12 15 17 10"></polyline>
209                        <line x1="12" y1="15" x2="12" y2="3"></line>
210                    </svg>
211                    Download Video
212                `;
213                
214            } catch (error) {
215                console.error('Download failed:', error);
216                statusMsg.className = 'download-status error';
217                statusMsg.textContent = 'Download failed: ' + error.message;
218                
219                downloadBtn.disabled = false;
220                downloadBtn.innerHTML = `
221                    <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
222                        <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
223                        <polyline points="7 10 12 15 17 10"></polyline>
224                        <line x1="12" y1="15" x2="12" y2="3"></line>
225                    </svg>
226                    Download Video
227                `;
228            }
229        });
230        
231        console.log('Download button created successfully');
232    }
233
234    function init() {
235        console.log('Initializing Video Downloader');
236        
237        // Wait for the page to be fully loaded
238        if (document.readyState === 'loading') {
239            document.addEventListener('DOMContentLoaded', () => {
240                setTimeout(createDownloadButton, 1000);
241            });
242        } else {
243            setTimeout(createDownloadButton, 1000);
244        }
245    }
246
247    init();
248})();
Video Downloader for PornforUs | Robomonkey