Size
15.0 KB
Version
1.0.1
Created
Feb 2, 2026
Updated
15 days ago
1// ==UserScript==
2// @name Website Blocker
3// @description Block distracting websites with a customizable blocklist
4// @version 1.0.1
5// @match *://*/*
6// @icon https://robomonkey.io/favicon.ico
7// ==/UserScript==
8(function() {
9 'use strict';
10
11 // Initialize the extension
12 async function init() {
13 console.log('Website Blocker extension loaded');
14
15 // Check if current site is blocked
16 await checkAndBlockSite();
17
18 // Add settings button to page
19 addSettingsButton();
20 }
21
22 // Check if the current website should be blocked
23 async function checkAndBlockSite() {
24 const currentUrl = window.location.hostname;
25 console.log('Checking if site is blocked:', currentUrl);
26
27 // Get blocked sites list from storage
28 const blockedSites = await getBlockedSites();
29
30 // Check if current site matches any blocked site
31 const isBlocked = blockedSites.some(site => {
32 // Remove protocol and www if present
33 const cleanSite = site.replace(/^(https?:\/\/)?(www\.)?/, '').toLowerCase();
34 const cleanCurrent = currentUrl.replace(/^www\./, '').toLowerCase();
35
36 // Check if current site contains the blocked site
37 return cleanCurrent.includes(cleanSite) || cleanCurrent === cleanSite;
38 });
39
40 if (isBlocked) {
41 console.log('Site is blocked, showing block page');
42 showBlockPage();
43 }
44 }
45
46 // Get blocked sites from storage
47 async function getBlockedSites() {
48 const sites = await GM.getValue('blockedSites', '[]');
49 return JSON.parse(sites);
50 }
51
52 // Save blocked sites to storage
53 async function saveBlockedSites(sites) {
54 await GM.setValue('blockedSites', JSON.stringify(sites));
55 }
56
57 // Show block page
58 function showBlockPage() {
59 // Clear the page
60 document.documentElement.innerHTML = '';
61
62 // Create block page
63 const blockPage = document.createElement('div');
64 blockPage.style.cssText = `
65 position: fixed;
66 top: 0;
67 left: 0;
68 width: 100%;
69 height: 100%;
70 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
71 display: flex;
72 flex-direction: column;
73 justify-content: center;
74 align-items: center;
75 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
76 z-index: 999999;
77 `;
78
79 blockPage.innerHTML = `
80 <div style="text-align: center; color: white; max-width: 600px; padding: 40px;">
81 <div style="font-size: 80px; margin-bottom: 20px;">🚫</div>
82 <h1 style="font-size: 48px; margin: 0 0 20px 0; font-weight: 700;">Site Blocked</h1>
83 <p style="font-size: 20px; margin: 0 0 30px 0; opacity: 0.9;">
84 This website is on your block list. Stay focused!
85 </p>
86 <div style="font-size: 16px; margin-bottom: 30px; opacity: 0.8;">
87 <strong>${window.location.hostname}</strong>
88 </div>
89 <button id="unblock-btn" style="
90 background: rgba(255, 255, 255, 0.2);
91 border: 2px solid white;
92 color: white;
93 padding: 12px 30px;
94 font-size: 16px;
95 border-radius: 8px;
96 cursor: pointer;
97 font-weight: 600;
98 transition: all 0.3s ease;
99 margin-right: 10px;
100 ">Manage Blocked Sites</button>
101 <button id="go-back-btn" style="
102 background: white;
103 border: 2px solid white;
104 color: #667eea;
105 padding: 12px 30px;
106 font-size: 16px;
107 border-radius: 8px;
108 cursor: pointer;
109 font-weight: 600;
110 transition: all 0.3s ease;
111 ">Go Back</button>
112 </div>
113 `;
114
115 document.documentElement.appendChild(blockPage);
116
117 // Add hover effects
118 const unblockBtn = blockPage.querySelector('#unblock-btn');
119 const goBackBtn = blockPage.querySelector('#go-back-btn');
120
121 unblockBtn.addEventListener('mouseenter', () => {
122 unblockBtn.style.background = 'rgba(255, 255, 255, 0.3)';
123 unblockBtn.style.transform = 'translateY(-2px)';
124 });
125 unblockBtn.addEventListener('mouseleave', () => {
126 unblockBtn.style.background = 'rgba(255, 255, 255, 0.2)';
127 unblockBtn.style.transform = 'translateY(0)';
128 });
129
130 goBackBtn.addEventListener('mouseenter', () => {
131 goBackBtn.style.background = '#f0f0f0';
132 goBackBtn.style.transform = 'translateY(-2px)';
133 });
134 goBackBtn.addEventListener('mouseleave', () => {
135 goBackBtn.style.background = 'white';
136 goBackBtn.style.transform = 'translateY(0)';
137 });
138
139 // Add event listeners
140 unblockBtn.addEventListener('click', () => {
141 showSettingsModal();
142 });
143
144 goBackBtn.addEventListener('click', () => {
145 window.history.back();
146 });
147 }
148
149 // Add settings button to page
150 function addSettingsButton() {
151 const settingsBtn = document.createElement('button');
152 settingsBtn.id = 'website-blocker-settings-btn';
153 settingsBtn.innerHTML = '🚫';
154 settingsBtn.title = 'Website Blocker Settings';
155 settingsBtn.style.cssText = `
156 position: fixed;
157 bottom: 20px;
158 right: 20px;
159 width: 56px;
160 height: 56px;
161 border-radius: 50%;
162 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
163 border: none;
164 color: white;
165 font-size: 24px;
166 cursor: pointer;
167 box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
168 z-index: 999998;
169 transition: all 0.3s ease;
170 display: flex;
171 align-items: center;
172 justify-content: center;
173 `;
174
175 settingsBtn.addEventListener('mouseenter', () => {
176 settingsBtn.style.transform = 'scale(1.1)';
177 settingsBtn.style.boxShadow = '0 6px 16px rgba(0, 0, 0, 0.2)';
178 });
179
180 settingsBtn.addEventListener('mouseleave', () => {
181 settingsBtn.style.transform = 'scale(1)';
182 settingsBtn.style.boxShadow = '0 4px 12px rgba(0, 0, 0, 0.15)';
183 });
184
185 settingsBtn.addEventListener('click', () => {
186 showSettingsModal();
187 });
188
189 document.body.appendChild(settingsBtn);
190 }
191
192 // Show settings modal
193 async function showSettingsModal() {
194 // Remove existing modal if any
195 const existingModal = document.getElementById('website-blocker-modal');
196 if (existingModal) {
197 existingModal.remove();
198 }
199
200 const blockedSites = await getBlockedSites();
201
202 const modal = document.createElement('div');
203 modal.id = 'website-blocker-modal';
204 modal.style.cssText = `
205 position: fixed;
206 top: 0;
207 left: 0;
208 width: 100%;
209 height: 100%;
210 background: rgba(0, 0, 0, 0.7);
211 display: flex;
212 justify-content: center;
213 align-items: center;
214 z-index: 999999;
215 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
216 `;
217
218 const modalContent = document.createElement('div');
219 modalContent.style.cssText = `
220 background: white;
221 border-radius: 12px;
222 padding: 30px;
223 max-width: 500px;
224 width: 90%;
225 max-height: 80vh;
226 overflow-y: auto;
227 box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
228 `;
229
230 modalContent.innerHTML = `
231 <h2 style="margin: 0 0 20px 0; color: #333; font-size: 24px; font-weight: 700;">Website Blocker Settings</h2>
232
233 <div style="margin-bottom: 20px;">
234 <label style="display: block; margin-bottom: 8px; color: #555; font-weight: 600;">Add Website to Block:</label>
235 <div style="display: flex; gap: 10px;">
236 <input type="text" id="new-site-input" placeholder="example.com" style="
237 flex: 1;
238 padding: 10px 15px;
239 border: 2px solid #e0e0e0;
240 border-radius: 8px;
241 font-size: 14px;
242 outline: none;
243 transition: border-color 0.3s ease;
244 ">
245 <button id="add-site-btn" style="
246 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
247 color: white;
248 border: none;
249 padding: 10px 20px;
250 border-radius: 8px;
251 cursor: pointer;
252 font-weight: 600;
253 font-size: 14px;
254 transition: all 0.3s ease;
255 ">Add</button>
256 </div>
257 </div>
258
259 <div style="margin-bottom: 20px;">
260 <h3 style="margin: 0 0 15px 0; color: #333; font-size: 18px; font-weight: 600;">Blocked Websites:</h3>
261 <div id="blocked-sites-list" style="
262 max-height: 300px;
263 overflow-y: auto;
264 ">
265 ${blockedSites.length === 0 ?
266 '<p style="color: #999; text-align: center; padding: 20px;">No websites blocked yet</p>' :
267 blockedSites.map((site, index) => `
268 <div class="blocked-site-item" data-index="${index}" style="
269 display: flex;
270 justify-content: space-between;
271 align-items: center;
272 padding: 12px 15px;
273 background: #f8f9fa;
274 border-radius: 8px;
275 margin-bottom: 8px;
276 ">
277 <span style="color: #333; font-size: 14px;">${site}</span>
278 <button class="remove-site-btn" data-site="${site}" style="
279 background: #ff4757;
280 color: white;
281 border: none;
282 padding: 6px 12px;
283 border-radius: 6px;
284 cursor: pointer;
285 font-size: 12px;
286 font-weight: 600;
287 transition: all 0.3s ease;
288 ">Remove</button>
289 </div>
290 `).join('')
291 }
292 </div>
293 </div>
294
295 <div style="display: flex; justify-content: flex-end; gap: 10px;">
296 <button id="close-modal-btn" style="
297 background: #e0e0e0;
298 color: #333;
299 border: none;
300 padding: 10px 20px;
301 border-radius: 8px;
302 cursor: pointer;
303 font-weight: 600;
304 font-size: 14px;
305 transition: all 0.3s ease;
306 ">Close</button>
307 </div>
308 `;
309
310 modal.appendChild(modalContent);
311 document.body.appendChild(modal);
312
313 // Add input focus effect
314 const input = modal.querySelector('#new-site-input');
315 input.addEventListener('focus', () => {
316 input.style.borderColor = '#667eea';
317 });
318 input.addEventListener('blur', () => {
319 input.style.borderColor = '#e0e0e0';
320 });
321
322 // Add site button
323 const addBtn = modal.querySelector('#add-site-btn');
324 addBtn.addEventListener('mouseenter', () => {
325 addBtn.style.transform = 'translateY(-2px)';
326 addBtn.style.boxShadow = '0 4px 12px rgba(102, 126, 234, 0.4)';
327 });
328 addBtn.addEventListener('mouseleave', () => {
329 addBtn.style.transform = 'translateY(0)';
330 addBtn.style.boxShadow = 'none';
331 });
332
333 addBtn.addEventListener('click', async () => {
334 const newSite = input.value.trim();
335 if (newSite) {
336 const sites = await getBlockedSites();
337 if (!sites.includes(newSite)) {
338 sites.push(newSite);
339 await saveBlockedSites(sites);
340 input.value = '';
341 showSettingsModal(); // Refresh modal
342 console.log('Added site to block list:', newSite);
343 }
344 }
345 });
346
347 // Allow Enter key to add site
348 input.addEventListener('keypress', (e) => {
349 if (e.key === 'Enter') {
350 addBtn.click();
351 }
352 });
353
354 // Remove site buttons
355 const removeButtons = modal.querySelectorAll('.remove-site-btn');
356 removeButtons.forEach(btn => {
357 btn.addEventListener('mouseenter', () => {
358 btn.style.background = '#ee5a6f';
359 btn.style.transform = 'translateY(-2px)';
360 });
361 btn.addEventListener('mouseleave', () => {
362 btn.style.background = '#ff4757';
363 btn.style.transform = 'translateY(0)';
364 });
365
366 btn.addEventListener('click', async () => {
367 const siteToRemove = btn.dataset.site;
368 const sites = await getBlockedSites();
369 const updatedSites = sites.filter(site => site !== siteToRemove);
370 await saveBlockedSites(updatedSites);
371 showSettingsModal(); // Refresh modal
372 console.log('Removed site from block list:', siteToRemove);
373 });
374 });
375
376 // Close button
377 const closeBtn = modal.querySelector('#close-modal-btn');
378 closeBtn.addEventListener('mouseenter', () => {
379 closeBtn.style.background = '#d0d0d0';
380 });
381 closeBtn.addEventListener('mouseleave', () => {
382 closeBtn.style.background = '#e0e0e0';
383 });
384
385 closeBtn.addEventListener('click', () => {
386 modal.remove();
387 });
388
389 // Close on background click
390 modal.addEventListener('click', (e) => {
391 if (e.target === modal) {
392 modal.remove();
393 }
394 });
395 }
396
397 // Start the extension
398 init();
399})();