Size
5.7 KB
Version
1.0.1
Created
Feb 15, 2026
Updated
22 days ago
1// ==UserScript==
2// @name Google Images Bikini Filter
3// @description A new extension
4// @version 1.0.1
5// @match https://*.google.com/*
6// ==/UserScript==
7(function() {
8 'use strict';
9
10 console.log('Google Images Bikini Filter extension loaded');
11
12 // Debounce function to avoid excessive calls
13 function debounce(func, wait) {
14 let timeout;
15 return function executedFunction(...args) {
16 const later = () => {
17 clearTimeout(timeout);
18 func(...args);
19 };
20 clearTimeout(timeout);
21 timeout = setTimeout(later, wait);
22 };
23 }
24
25 // Check if we're on Google Images search
26 function isGoogleImagesPage() {
27 return window.location.href.includes('google.com') &&
28 (window.location.href.includes('udm=2') ||
29 window.location.href.includes('tbm=isch') ||
30 document.querySelector('div[data-ved]') !== null);
31 }
32
33 // Process images and filter for bikini content
34 async function filterImages() {
35 if (!isGoogleImagesPage()) {
36 console.log('Not on Google Images page, skipping filter');
37 return;
38 }
39
40 console.log('Starting bikini filter process...');
41
42 // Find all image containers
43 const imageContainers = document.querySelectorAll('div[data-ved][jsname]');
44 console.log(`Found ${imageContainers.length} image containers`);
45
46 if (imageContainers.length === 0) {
47 console.log('No image containers found, will retry...');
48 return;
49 }
50
51 for (const container of imageContainers) {
52 // Skip if already processed
53 if (container.dataset.bikiniProcessed === 'true') {
54 continue;
55 }
56
57 // Mark as processed
58 container.dataset.bikiniProcessed = 'true';
59
60 // Get the image element
61 const img = container.querySelector('img');
62 if (!img || !img.src || img.src.startsWith('data:')) {
63 continue;
64 }
65
66 // Get alt text and surrounding text for context
67 const altText = img.alt || '';
68 const containerText = container.textContent || '';
69 const context = `Image alt text: "${altText}". Container text: "${containerText.substring(0, 200)}"`;
70
71 try {
72 console.log('Analyzing image:', img.src.substring(0, 100));
73
74 // Use AI to determine if this is a bikini picture
75 const analysis = await RM.aiCall(
76 `Analyze if this image is related to bikinis, swimwear, or beach attire based on the context: ${context}. Consider the image description and surrounding text.`,
77 {
78 type: "json_schema",
79 json_schema: {
80 name: "bikini_detection",
81 schema: {
82 type: "object",
83 properties: {
84 isBikini: {
85 type: "boolean",
86 description: "True if the image is related to bikinis, swimwear, or beach attire"
87 },
88 confidence: {
89 type: "number",
90 minimum: 0,
91 maximum: 1,
92 description: "Confidence level of the detection"
93 },
94 reason: {
95 type: "string",
96 description: "Brief explanation of the decision"
97 }
98 },
99 required: ["isBikini", "confidence", "reason"]
100 }
101 }
102 }
103 );
104
105 console.log('Analysis result:', analysis);
106
107 // Hide images that are NOT bikini-related
108 if (!analysis.isBikini || analysis.confidence < 0.5) {
109 container.style.display = 'none';
110 console.log('Hiding non-bikini image:', analysis.reason);
111 } else {
112 container.style.display = '';
113 console.log('Keeping bikini image:', analysis.reason);
114 }
115
116 } catch (error) {
117 console.error('Error analyzing image:', error);
118 // On error, keep the image visible to avoid hiding everything
119 }
120 }
121
122 console.log('Bikini filter process completed');
123 }
124
125 // Initialize the extension
126 async function init() {
127 console.log('Initializing Google Images Bikini Filter...');
128
129 if (!isGoogleImagesPage()) {
130 console.log('Not on Google Images page');
131 return;
132 }
133
134 // Wait for images to load
135 setTimeout(() => {
136 filterImages();
137 }, 2000);
138
139 // Watch for new images being loaded (infinite scroll)
140 const debouncedFilter = debounce(filterImages, 1000);
141
142 const observer = new MutationObserver(debouncedFilter);
143
144 observer.observe(document.body, {
145 childList: true,
146 subtree: true
147 });
148
149 console.log('Bikini filter initialized and watching for new images');
150 }
151
152 // Start when page is ready
153 if (document.readyState === 'loading') {
154 document.addEventListener('DOMContentLoaded', init);
155 } else {
156 init();
157 }
158
159})();