PornoLab Torrent Name Copier

Copy torrent file name to clipboard with one click

Size

7.0 KB

Version

1.1.8

Created

Jan 21, 2026

Updated

about 1 month ago

1// ==UserScript==
2// @name		PornoLab Torrent Name Copier
3// @description		Copy torrent file name to clipboard with one click
4// @version		1.1.8
5// @match		https://*.pornolab.net/*
6// @icon		https://static.pornolab.net/favicon.ico
7// @grant		GM.setClipboard
8// ==/UserScript==
9(function() {
10    'use strict';
11
12    console.log('PornoLab Torrent File Name Copier loaded');
13
14    // Function to extract just the filename from the file list text
15    function extractFileName(fileListText) {
16        // Remove the file size info (everything after the filename)
17        // The format is: "filename.mp4 <i><s>size</s> (bytes)</i>"
18        const match = fileListText.match(/^(.+?\.mp4)/);
19        return match ? match[1].trim() : fileListText.trim();
20    }
21
22    // Function to wait for the file list to load
23    async function waitForFileList() {
24        const maxAttempts = 20; // Wait up to 10 seconds
25        let attempts = 0;
26
27        while (attempts < maxAttempts) {
28            const fileListElement = document.querySelector('#tor-filelist');
29            if (fileListElement) {
30                const text = fileListElement.textContent.trim();
31                // Check if it's not loading and contains .mp4
32                if (text && !text.includes('загружается') && text.includes('.mp4')) {
33                    console.log('File list loaded successfully');
34                    return extractFileName(text);
35                }
36            }
37            await new Promise(resolve => setTimeout(resolve, 500));
38            attempts++;
39        }
40        
41        console.error('File list did not load in time');
42        return null;
43    }
44
45    // Cross-platform clipboard function
46    async function copyToClipboard(text) {
47        // Try GM.setClipboard first (works in most userscript managers)
48        if (typeof GM !== 'undefined' && GM.setClipboard) {
49            await GM.setClipboard(text);
50            return;
51        }
52        
53        // Fallback to navigator.clipboard API
54        if (navigator.clipboard && navigator.clipboard.writeText) {
55            await navigator.clipboard.writeText(text);
56            return;
57        }
58        
59        // Last resort: create a temporary textarea
60        const textarea = document.createElement('textarea');
61        textarea.value = text;
62        textarea.style.position = 'fixed';
63        textarea.style.opacity = '0';
64        document.body.appendChild(textarea);
65        textarea.select();
66        document.execCommand('copy');
67        document.body.removeChild(textarea);
68    }
69
70    // Function to initialize the copy button
71    async function init() {
72        // Find the torrent title element at the top of the page
73        const titleElement = document.querySelector('#topic-title');
74        
75        if (!titleElement) {
76            console.log('Torrent title not found on this page');
77            return;
78        }
79
80        // Create the copy button immediately
81        const copyButton = document.createElement('button');
82        copyButton.textContent = '📋 Copy File Name';
83        copyButton.style.cssText = `
84            margin-left: 10px;
85            padding: 8px 16px;
86            background-color: #4CAF50;
87            color: white;
88            border: none;
89            border-radius: 4px;
90            cursor: pointer;
91            font-size: 14px;
92            font-weight: bold;
93            transition: background-color 0.3s;
94        `;
95
96        // Add hover effect
97        copyButton.addEventListener('mouseenter', () => {
98            copyButton.style.backgroundColor = '#45a049';
99        });
100
101        copyButton.addEventListener('mouseleave', () => {
102            copyButton.style.backgroundColor = '#4CAF50';
103        });
104
105        // Insert the button next to the title immediately
106        const titleContainer = titleElement.parentElement;
107        if (titleContainer) {
108            titleContainer.appendChild(copyButton);
109            console.log('Copy button added successfully');
110        }
111
112        // Now load the file name in the background
113        const fileListBtn = document.querySelector('#tor-filelist-btn');
114        
115        if (!fileListBtn) {
116            console.log('File list button not found on this page');
117            copyButton.textContent = '✗ No Files';
118            copyButton.style.backgroundColor = '#f44336';
119            copyButton.disabled = true;
120            return;
121        }
122
123        // Check if file list is already loaded
124        const fileListElement = document.querySelector('#tor-filelist');
125        const isAlreadyLoaded = fileListElement && 
126                                fileListElement.textContent.trim() && 
127                                !fileListElement.textContent.includes('загружается') && 
128                                fileListElement.textContent.includes('.mp4');
129
130        // Click the button to reveal the file list if not already loaded
131        if (!isAlreadyLoaded) {
132            const fileListWrap = document.querySelector('#tor-fl-wrap');
133            if (!fileListWrap || fileListWrap.style.display === 'none') {
134                fileListBtn.click();
135                console.log('Clicked file list button to reveal files');
136            } else {
137                // File list wrap exists but might be loading, click anyway to ensure it loads
138                fileListBtn.click();
139                console.log('File list wrap exists, clicking button to load files');
140            }
141        }
142
143        // Wait for the file list to load
144        const fileName = await waitForFileList();
145        
146        if (!fileName) {
147            console.error('Could not get file name');
148            copyButton.textContent = '✗ Failed to Load';
149            copyButton.style.backgroundColor = '#f44336';
150            copyButton.disabled = true;
151            return;
152        }
153
154        console.log('Found file name:', fileName);
155
156        // Add click handler to copy the file name
157        copyButton.addEventListener('click', async () => {
158            try {
159                await copyToClipboard(fileName);
160                console.log('File name copied to clipboard:', fileName);
161                
162                // Visual feedback
163                const originalText = copyButton.textContent;
164                copyButton.textContent = '✓ Copied!';
165                copyButton.style.backgroundColor = '#2196F3';
166                
167                setTimeout(() => {
168                    copyButton.textContent = originalText;
169                    copyButton.style.backgroundColor = '#4CAF50';
170                }, 2000);
171            } catch (error) {
172                console.error('Failed to copy to clipboard:', error);
173                copyButton.textContent = '✗ Failed';
174                copyButton.style.backgroundColor = '#f44336';
175                
176                setTimeout(() => {
177                    copyButton.textContent = '📋 Copy File Name';
178                    copyButton.style.backgroundColor = '#4CAF50';
179                }, 2000);
180            }
181        });
182    }
183
184    // Wait for the page to be fully loaded
185    if (document.readyState === 'loading') {
186        document.addEventListener('DOMContentLoaded', init);
187    } else {
188        init();
189    }
190})();