Testbook Ad Blocker & PDF Downloader

A new extension

Size

8.0 KB

Version

1.0.1

Created

Nov 10, 2025

Updated

about 1 month ago

1// ==UserScript==
2// @name		Testbook Ad Blocker & PDF Downloader
3// @description		A new extension
4// @version		1.0.1
5// @match		https://*.testbook.com/*
6// @icon		https://testbook.com/assets/img/brand/logo-32x32.png
7// @require		https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js
8// ==/UserScript==
9(function() {
10    'use strict';
11
12    console.log('Testbook Ad Blocker & PDF Downloader initialized');
13
14    // Function to remove ads, banners, and login/signup elements
15    function removeAdsAndPromotions() {
16        console.log('Removing ads, banners, and login/signup elements...');
17
18        // Remove super banner ads
19        const superBanners = document.querySelectorAll('.super-banner, a[href*="super-pass-live-coaching"]');
20        superBanners.forEach(banner => {
21            console.log('Removing super banner:', banner);
22            banner.remove();
23        });
24
25        // Remove signup buttons
26        const signupButtons = document.querySelectorAll('.signup-button, .signup-button-link, a[href*="login?tile=signup"]');
27        signupButtons.forEach(button => {
28            console.log('Removing signup button:', button);
29            button.remove();
30        });
31
32        // Remove sticky signup component
33        const stickySignup = document.querySelectorAll('.sticky-signup__content, .sticky-signup');
34        stickySignup.forEach(element => {
35            console.log('Removing sticky signup:', element);
36            element.remove();
37        });
38
39        // Remove signup banner
40        const signupBanner = document.querySelectorAll('.signup-banner');
41        signupBanner.forEach(element => {
42            console.log('Removing signup banner:', element);
43            element.remove();
44        });
45
46        // Remove "Get Started" buttons
47        const getStartedButtons = document.querySelectorAll('a.pure-button[href*="login"]');
48        getStartedButtons.forEach(button => {
49            if (button.textContent.includes('Get Started') || button.textContent.includes('Sign Up')) {
50                console.log('Removing get started button:', button);
51                button.remove();
52            }
53        });
54
55        // Remove download app buttons
56        const downloadAppButtons = document.querySelectorAll('.download-app-btn');
57        downloadAppButtons.forEach(button => {
58            console.log('Removing download app button:', button);
59            button.remove();
60        });
61
62        // Remove the fake "Download Solution PDF" buttons that require login
63        const fakeDownloadButtons = document.querySelectorAll('a.solpdf-download-link[href*="login"]');
64        fakeDownloadButtons.forEach(button => {
65            console.log('Removing fake download button:', button);
66            button.remove();
67        });
68
69        // Remove promotional containers
70        const promoContainers = document.querySelectorAll('.buttons-container a[href*="login"]');
71        promoContainers.forEach(container => {
72            console.log('Removing promo container:', container);
73            container.remove();
74        });
75
76        console.log('Ad removal complete');
77    }
78
79    // Function to add PDF download button
80    function addPDFDownloadButton() {
81        console.log('Adding PDF download button...');
82
83        // Find the question header area
84        const questionHeader = document.querySelector('.question__header');
85        if (!questionHeader) {
86            console.error('Question header not found');
87            return;
88        }
89
90        // Create the download button
91        const downloadButton = document.createElement('button');
92        downloadButton.id = 'custom-pdf-download-btn';
93        downloadButton.className = 'pure-button pure-button-error';
94        downloadButton.innerHTML = '📄 Download as PDF';
95        downloadButton.style.cssText = `
96            background-color: #d9534f;
97            color: white;
98            padding: 10px 20px;
99            border: none;
100            border-radius: 4px;
101            cursor: pointer;
102            font-size: 14px;
103            font-weight: bold;
104            transition: background-color 0.3s;
105        `;
106
107        // Add hover effect
108        downloadButton.addEventListener('mouseenter', () => {
109            downloadButton.style.backgroundColor = '#c9302c';
110        });
111        downloadButton.addEventListener('mouseleave', () => {
112            downloadButton.style.backgroundColor = '#d9534f';
113        });
114
115        // Add click handler
116        downloadButton.addEventListener('click', generatePDF);
117
118        // Append button to header
119        questionHeader.appendChild(downloadButton);
120        console.log('PDF download button added successfully');
121    }
122
123    // Function to generate PDF
124    async function generatePDF() {
125        console.log('Generating PDF...');
126
127        const button = document.getElementById('custom-pdf-download-btn');
128        const originalText = button.innerHTML;
129        button.innerHTML = '⏳ Generating PDF...';
130        button.disabled = true;
131
132        try {
133            // Get the main content container
134            const mainContainer = document.querySelector('.ques-container');
135            if (!mainContainer) {
136                throw new Error('Content container not found');
137            }
138
139            // Clone the content to avoid modifying the original
140            const contentClone = mainContainer.cloneNode(true);
141
142            // Remove any remaining login/signup elements from the clone
143            const unwantedElements = contentClone.querySelectorAll('a[href*="login"], .signup-button, .solpdf-download-link');
144            unwantedElements.forEach(el => el.remove());
145
146            // Configure PDF options
147            const opt = {
148                margin: [10, 10, 10, 10],
149                filename: 'testbook-question-answer.pdf',
150                image: { type: 'jpeg', quality: 0.98 },
151                html2canvas: { 
152                    scale: 2,
153                    useCORS: true,
154                    logging: false,
155                    letterRendering: true
156                },
157                jsPDF: { 
158                    unit: 'mm', 
159                    format: 'a4', 
160                    orientation: 'portrait' 
161                }
162            };
163
164            // Generate PDF
165            await html2pdf().set(opt).from(contentClone).save();
166
167            console.log('PDF generated successfully');
168            button.innerHTML = '✅ PDF Downloaded!';
169            
170            // Reset button after 3 seconds
171            setTimeout(() => {
172                button.innerHTML = originalText;
173                button.disabled = false;
174            }, 3000);
175
176        } catch (error) {
177            console.error('Error generating PDF:', error);
178            button.innerHTML = '❌ Error - Try Again';
179            button.disabled = false;
180            
181            setTimeout(() => {
182                button.innerHTML = originalText;
183            }, 3000);
184        }
185    }
186
187    // Debounce function for MutationObserver
188    function debounce(func, wait) {
189        let timeout;
190        return function executedFunction(...args) {
191            const later = () => {
192                clearTimeout(timeout);
193                func(...args);
194            };
195            clearTimeout(timeout);
196            timeout = setTimeout(later, wait);
197        };
198    }
199
200    // Initialize the extension
201    function init() {
202        console.log('Initializing Testbook Ad Blocker & PDF Downloader...');
203
204        // Wait for the page to be fully loaded
205        if (document.readyState === 'loading') {
206            document.addEventListener('DOMContentLoaded', init);
207            return;
208        }
209
210        // Remove ads and add PDF button
211        removeAdsAndPromotions();
212        addPDFDownloadButton();
213
214        // Observe DOM changes to remove dynamically loaded ads
215        const debouncedRemoveAds = debounce(removeAdsAndPromotions, 500);
216        const observer = new MutationObserver(debouncedRemoveAds);
217        
218        observer.observe(document.body, {
219            childList: true,
220            subtree: true
221        });
222
223        console.log('Initialization complete');
224    }
225
226    // Start the extension
227    init();
228
229})();
Testbook Ad Blocker & PDF Downloader | Robomonkey