diff --git a/1000_bots_webextension/background.js b/1000_bots_webextension/background.js index b0ecc22..286273c 100644 --- a/1000_bots_webextension/background.js +++ b/1000_bots_webextension/background.js @@ -20,22 +20,24 @@ "use strict"; +const DEBUG = false; + // Use chrome or browser depending on the environment -var browser = chrome || browser; +const browser = chrome || browser; // Custom user-agent to spoof Googlebot -var user_agent = +const user_agent = "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"; -var target_urls = "*://*/*"; +const target_urls = "*://*/*"; // Duration to display the injected HTML (in milliseconds) const DISPLAY_DURATION = 8000; // Set to 8 seconds // Initialize storage for duration -browser.storage.local +browser.storage.sync .set({ duration: DISPLAY_DURATION }) .then(() => { - console.log("Duration set to:", DISPLAY_DURATION); + if (DEBUG) console.log("Duration set to:", DISPLAY_DURATION); }) .catch((error) => { console.error("Error setting duration:", error); @@ -43,14 +45,16 @@ browser.storage.local // Set extension status to ON function set_extension_status_ON() { - browser.storage.local - .set({ status: 1 }) + browser.storage.sync + .set({ status: 1, bannerInjected: false, debug: DEBUG }) .then(() => { - console.log("Extension status set to ON"); + if (DEBUG) console.log("Extension status set to ON"); return browser.action.setIcon({ path: "icon_ON_48.png" }); }) .then(() => { - return browser.action.setTitle({ title: "1000 Bots" }); + return browser.action.setTitle({ + title: "You are now surfing the web as a bot 🤖", + }); }) .then(() => { // Start user-agent spoofing @@ -71,14 +75,16 @@ function set_extension_status_ON() { // Set extension status to OFF function set_extension_status_OFF() { - browser.storage.local + browser.storage.sync .set({ status: 0 }) .then(() => { - console.log("Extension status set to OFF"); + if (DEBUG) console.log("Extension status set to OFF"); return browser.action.setIcon({ path: "icon_OFF_48.png" }); }) .then(() => { - return browser.action.setTitle({ title: "1000 Bots activate" }); + return browser.action.setTitle({ + title: "Click here to refuse to be human 🤖", + }); }) .then(() => { // Remove the content from all active tabs @@ -99,7 +105,7 @@ function set_extension_status_OFF() { // Toggle the icon between ON and OFF function update_icon() { - browser.storage.local + browser.storage.sync .get("status") .then((result) => { if (result.status === 0) { @@ -143,7 +149,10 @@ function startUserAgentSpoofing() { removeRuleIds: [], }) .then(() => { - return console.log("User-Agent spoofing rules added successfully."); + if (DEBUG) + return console.log( + "User-Agent spoofing rules added successfully." + ); }) .then(() => {}) .catch((error) => { @@ -158,11 +167,12 @@ function stopUserAgentSpoofing() { removeRuleIds: [1], }) .then(() => { - console.log("User-Agent spoofing rules removed successfully."); + if (DEBUG) + console.log("User-Agent spoofing rules removed successfully."); }) .then(() => { // Clear the bannerInjected flag when stopping the extension - return browser.storage.local.set({ bannerInjected: false }); + return browser.storage.sync.set({ bannerInjected: false }); }) .catch((error) => { console.error("Error removing rules:", error); @@ -176,7 +186,7 @@ function refreshAllTabs() { browser.tabs .reload(tab.id) .then(() => { - console.log(`Refreshed tab: ${tab.id}`); + if (DEBUG) console.log(`Refreshed tab: ${tab.id}`); }) .catch((error) => { console.error(`Error refreshing tab ${tab.id}:`, error); @@ -190,33 +200,57 @@ function injectContentScript() { return browser.tabs .query({}) .then((tabs) => { - return Promise.all( - tabs.map((tab) => { - // Check if the tab is not a chrome URL - if (!tab.url.startsWith("chrome://")) { - return browser.scripting - .executeScript({ - target: { tabId: tab.id }, - files: ["content.js"], - }) - .then(() => { + // Create an array of promises for each tab + const promises = tabs.map((tab) => { + // Check if the URL is not something like chrome:// or about:// etc. + if (tab.url.startsWith("https://")) { + return browser.scripting + .executeScript({ + target: { tabId: tab.id }, + files: ["content.js"], + }) + .then(() => { + if (DEBUG) console.log( `Content script injected into tab ${tab.id}` ); - }) - .catch((error) => { - console.error( - `Error injecting content script into tab ${tab.id}:`, - error - ); - }); - } else { + + // Use a hardcoded duration for removal + const duration = 80000; // 8 seconds or whatever you need + + // Set a timeout to remove the content after the hardcoded duration + setTimeout(() => { + browser.storage.sync.set({ + bannerInjected: true, + }); + if (DEBUG) + console.log( + "Duration expired. Removing content." + ); + removeInjectedContent(); // Ensure this is defined + }, duration); + }) + .catch((error) => { + console.error( + `Error injecting content script into tab ${tab.id}:`, + error + ); + }); + } else { + if (DEBUG) console.log( - `Skipped injecting content script into tab ${tab.id} (chrome:// URL)` + `Skipped injecting content script into tab ${tab.id} (chrome://, about:// URL or similar)` ); - } - }) - ); + return Promise.resolve(); // Return resolved promise for skipped tabs + } + }); + + // Return a promise that resolves when all injections are complete + return Promise.all(promises); + }) + .then(() => { + if (DEBUG) + console.log("All scripts injected and removal timers set."); }) .catch((error) => { console.error("Error querying tabs:", error); @@ -229,7 +263,7 @@ function removeInjectedContent() { .query({}) .then((tabs) => { tabs.forEach((tab) => { - if (!tab.url.startsWith("chrome://")) { + if (tab.url.startsWith("https://")) { browser.scripting .executeScript({ target: { tabId: tab.id }, @@ -242,9 +276,10 @@ function removeInjectedContent() { }, }) .then(() => { - console.log( - `Removed injected content from tab ${tab.id}` - ); + if (DEBUG) + console.log( + `Removed injected content from tab ${tab.id}` + ); }) .catch((error) => { console.error( @@ -253,9 +288,10 @@ function removeInjectedContent() { ); }); } else { - console.log( - `Skipped removing injected content from tab ${tab.id} (chrome:// URL)` - ); + if (DEBUG) + console.log( + `Skipped removing injected content from tab ${tab.id} (chrome://, about:// URL or similar)` + ); } }); }) diff --git a/1000_bots_webextension/background_chrome.js b/1000_bots_webextension/background_chrome.js new file mode 100644 index 0000000..286273c --- /dev/null +++ b/1000_bots_webextension/background_chrome.js @@ -0,0 +1,312 @@ +/* + 1000 Bots - Surf the Web as Googlebot + + Copyleft (C) 2020 !Mediengruppe Bitnik, connect@bitnik.org + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +"use strict"; + +const DEBUG = false; + +// Use chrome or browser depending on the environment +const browser = chrome || browser; + +// Custom user-agent to spoof Googlebot +const user_agent = + "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"; +const target_urls = "*://*/*"; + +// Duration to display the injected HTML (in milliseconds) +const DISPLAY_DURATION = 8000; // Set to 8 seconds + +// Initialize storage for duration +browser.storage.sync + .set({ duration: DISPLAY_DURATION }) + .then(() => { + if (DEBUG) console.log("Duration set to:", DISPLAY_DURATION); + }) + .catch((error) => { + console.error("Error setting duration:", error); + }); + +// Set extension status to ON +function set_extension_status_ON() { + browser.storage.sync + .set({ status: 1, bannerInjected: false, debug: DEBUG }) + .then(() => { + if (DEBUG) console.log("Extension status set to ON"); + return browser.action.setIcon({ path: "icon_ON_48.png" }); + }) + .then(() => { + return browser.action.setTitle({ + title: "You are now surfing the web as a bot 🤖", + }); + }) + .then(() => { + // Start user-agent spoofing + return startUserAgentSpoofing(); + }) + .then(() => { + // Refresh all tabs after starting user-agent spoofing + return refreshAllTabs(); + }) + .then(() => { + // Inject the content script into all active tabs after refreshing + return injectContentScript(); + }) + .catch((error) => { + console.error("Error setting extension status ON:", error); + }); +} + +// Set extension status to OFF +function set_extension_status_OFF() { + browser.storage.sync + .set({ status: 0 }) + .then(() => { + if (DEBUG) console.log("Extension status set to OFF"); + return browser.action.setIcon({ path: "icon_OFF_48.png" }); + }) + .then(() => { + return browser.action.setTitle({ + title: "Click here to refuse to be human 🤖", + }); + }) + .then(() => { + // Remove the content from all active tabs + return removeInjectedContent(); + }) + .then(() => { + // Stop user-agent spoofing + return stopUserAgentSpoofing(); + }) + .then(() => { + // Refresh all tabs before stopping the extension + return refreshAllTabs(); + }) + .catch((error) => { + console.error("Error setting extension status OFF:", error); + }); +} + +// Toggle the icon between ON and OFF +function update_icon() { + browser.storage.sync + .get("status") + .then((result) => { + if (result.status === 0) { + set_extension_status_ON(); + } else { + set_extension_status_OFF(); + } + }) + .catch((error) => { + console.error("Error fetching extension status:", error); + }); +} + +// Start user-agent spoofing +function startUserAgentSpoofing() { + const rules = [ + { + id: 1, + priority: 1, + action: { + type: "modifyHeaders", + requestHeaders: [ + { + operation: "set", + header: "User-Agent", + value: user_agent, + }, + ], + }, + condition: { + urlFilter: target_urls, + resourceTypes: ["main_frame"], + }, + }, + ]; + + // Add the rules + return browser.declarativeNetRequest + .updateDynamicRules({ + addRules: rules, + removeRuleIds: [], + }) + .then(() => { + if (DEBUG) + return console.log( + "User-Agent spoofing rules added successfully." + ); + }) + .then(() => {}) + .catch((error) => { + console.error("Error adding rules:", error); + }); +} + +// Stop user-agent spoofing +function stopUserAgentSpoofing() { + return browser.declarativeNetRequest + .updateDynamicRules({ + removeRuleIds: [1], + }) + .then(() => { + if (DEBUG) + console.log("User-Agent spoofing rules removed successfully."); + }) + .then(() => { + // Clear the bannerInjected flag when stopping the extension + return browser.storage.sync.set({ bannerInjected: false }); + }) + .catch((error) => { + console.error("Error removing rules:", error); + }); +} + +// Function to refresh all active tabs +function refreshAllTabs() { + return browser.tabs.query({}).then((tabs) => { + tabs.forEach((tab) => { + browser.tabs + .reload(tab.id) + .then(() => { + if (DEBUG) console.log(`Refreshed tab: ${tab.id}`); + }) + .catch((error) => { + console.error(`Error refreshing tab ${tab.id}:`, error); + }); + }); + }); +} + +// Inject the content.js script into all active tabs +function injectContentScript() { + return browser.tabs + .query({}) + .then((tabs) => { + // Create an array of promises for each tab + const promises = tabs.map((tab) => { + // Check if the URL is not something like chrome:// or about:// etc. + if (tab.url.startsWith("https://")) { + return browser.scripting + .executeScript({ + target: { tabId: tab.id }, + files: ["content.js"], + }) + .then(() => { + if (DEBUG) + console.log( + `Content script injected into tab ${tab.id}` + ); + + // Use a hardcoded duration for removal + const duration = 80000; // 8 seconds or whatever you need + + // Set a timeout to remove the content after the hardcoded duration + setTimeout(() => { + browser.storage.sync.set({ + bannerInjected: true, + }); + if (DEBUG) + console.log( + "Duration expired. Removing content." + ); + removeInjectedContent(); // Ensure this is defined + }, duration); + }) + .catch((error) => { + console.error( + `Error injecting content script into tab ${tab.id}:`, + error + ); + }); + } else { + if (DEBUG) + console.log( + `Skipped injecting content script into tab ${tab.id} (chrome://, about:// URL or similar)` + ); + return Promise.resolve(); // Return resolved promise for skipped tabs + } + }); + + // Return a promise that resolves when all injections are complete + return Promise.all(promises); + }) + .then(() => { + if (DEBUG) + console.log("All scripts injected and removal timers set."); + }) + .catch((error) => { + console.error("Error querying tabs:", error); + }); +} + +// Remove the content from all active tabs +function removeInjectedContent() { + return browser.tabs + .query({}) + .then((tabs) => { + tabs.forEach((tab) => { + if (tab.url.startsWith("https://")) { + browser.scripting + .executeScript({ + target: { tabId: tab.id }, + function: () => { + const banner = + document.querySelector(".extension-banner"); + if (banner && banner.parentNode) { + banner.parentNode.removeChild(banner); + } + }, + }) + .then(() => { + if (DEBUG) + console.log( + `Removed injected content from tab ${tab.id}` + ); + }) + .catch((error) => { + console.error( + `Error removing injected content from tab ${tab.id}:`, + error + ); + }); + } else { + if (DEBUG) + console.log( + `Skipped removing injected content from tab ${tab.id} (chrome://, about:// URL or similar)` + ); + } + }); + }) + .catch((error) => { + console.error( + "Error querying tabs for injected content removal:", + error + ); + }); +} + +// Event listeners for Manifest v3 Service Worker +browser.runtime.onInstalled.addListener(() => { + set_extension_status_OFF(); // Set status to OFF on installation/startup +}); + +// Handle browser action clicks to toggle status +browser.action.onClicked.addListener(update_icon); diff --git a/1000_bots_webextension/background_ff.js b/1000_bots_webextension/background_ff.js new file mode 100644 index 0000000..3680bca --- /dev/null +++ b/1000_bots_webextension/background_ff.js @@ -0,0 +1,207 @@ +/* + 1000 Bots - Surf the Web as Googlebot + + Copyleft (C) 2020 !Mediengruppe Bitnik, connect@bitnik.org + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +"use strict"; + +var browser = browser || chrome; +var user_agent = + "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"; +var target_urls = "*://*/*"; +var status = 0; + +const DEBUG = false; // Set to true to enable debug mode + +// Duration to display the injected HTML (in milliseconds) +const DISPLAY_DURATION = 8000; // Set to 8 seconds + +// Initialize storage for duration +browser.storage.sync.set( + { duration: DISPLAY_DURATION, debug: DEBUG }, + function () { + if (browser.runtime.lastError) { + console.error("Error setting duration:", browser.runtime.lastError); + } else { + if (DEBUG) console.log("Duration set to:", DISPLAY_DURATION); + } + } +); + +// Inject the content.js script into all active tabs +function injectContentScript() { + browser.tabs.query({}, (tabs) => { + tabs.forEach((tab) => { + // Check if the URL is not something like chrome:// or about:// etc. + if (tab.url.startsWith("https://")) { + browser.tabs.executeScript( + tab.id, + { file: "content.js" }, + () => { + if (browser.runtime.lastError) { + console.error( + `Error injecting content script into tab ${tab.id}:`, + browser.runtime.lastError + ); + } else { + if (DEBUG) + console.log( + `Content script injected into tab ${tab.id}` + ); + + // If the duration has passed, removeInjectedContent + const interval = setInterval(() => { + browser.storage.sync.get( + "duration", + (result) => { + if (browser.runtime.lastError) { + console.error( + "Error fetching duration:", + browser.runtime.lastError + ); + } else if (result.duration <= 0) { + clearInterval(interval); + removeInjectedContent(); + } + } + ); + }); + } + } + ); + } else { + if (DEBUG) + console.log( + `Skipped injecting content script into tab ${tab.id} (chrome://, about:// URL or similar)` + ); + } + }); + }); +} + +// Remove the content from all active tabs +function removeInjectedContent() { + browser.tabs.query({}, (tabs) => { + tabs.forEach((tab) => { + if (tab.url.startsWith("https://")) { + browser.tabs.executeScript( + tab.id, + { + code: ` + const banner = document.querySelector('.extension-banner'); + if (banner && banner.parentNode) { + banner.parentNode.removeChild(banner); + } + `, + }, + () => { + if (browser.runtime.lastError) { + console.error( + `Error removing injected content from tab ${tab.id}:`, + browser.runtime.lastError + ); + } else { + if (DEBUG) + console.log( + `Removed injected content from tab ${tab.id}` + ); + } + } + ); + } else { + if (DEBUG) + console.log( + `Skipped removing injected content from tab ${tab.id} (chrome://, about:// URL or similar)` + ); + } + }); + }); +} + +// Function to refresh all active tabs +function refreshAllTabs() { + browser.tabs.query({}, (tabs) => { + tabs.forEach((tab) => { + browser.tabs.reload(tab.id, () => { + if (browser.runtime.lastError) { + console.error( + `Error refreshing tab ${tab.id}:`, + browser.runtime.lastError + ); + } else { + if (DEBUG) console.log(`Refreshed tab: ${tab.id}`); + } + }); + }); + }); +} + +function set_extension_status_ON() { + status = 1; + if (DEBUG) console.log("Setting status to ON"); + browser.browserAction.setIcon({ path: "icon_ON_48.png" }); + browser.browserAction.setTitle({ + title: "You are now surfing the web as a bot 🤖", + }); + injectContentScript(); +} + +function set_extension_status_OFF() { + status = 0; + if (DEBUG) console.log("Setting status to OFF"); + browser.browserAction.setIcon({ path: "icon_OFF_48.png" }); + browser.browserAction.setTitle({ + title: "Click here to refuse to be human 🤖", + }); + removeInjectedContent(); + refreshAllTabs(); +} + +function update_icon() { + if (status == 0) { + set_extension_status_ON(); + } else { + set_extension_status_OFF(); + } +} + +function rewrite_user_agent_header(e) { + if (DEBUG) console.log("Browser http request!"); + + if (status == 0) { + if (DEBUG) console.log("Nothing to do"); + return { requestHeaders: e.requestHeaders }; + } + + for (var header of e.requestHeaders) { + if (header.name.toLowerCase() === "user-agent") { + header.value = user_agent; + } + } + if (DEBUG) console.log("Set user-agent header to: " + user_agent); + return { requestHeaders: e.requestHeaders }; +} + +browser.runtime.onStartup.addListener(set_extension_status_OFF); +browser.browserAction.onClicked.addListener(update_icon); + +browser.webRequest.onBeforeSendHeaders.addListener( + rewrite_user_agent_header, + { urls: [target_urls] }, + ["blocking", "requestHeaders"] +); diff --git a/1000_bots_webextension/content.js b/1000_bots_webextension/content.js index 0e72239..f9c47f9 100644 --- a/1000_bots_webextension/content.js +++ b/1000_bots_webextension/content.js @@ -1,94 +1,130 @@ +// Use chrome or browser depending on the environment +const browser = chrome || browser; + +let DEBUG; // Declare the DEBUG variable in the outer scope + +browser.storage.sync.get("debug").then((result) => { + DEBUG = result.debug; + console.log("DEBUG mode:", DEBUG); +}); + +// Duration to show the banner (in milliseconds) +let DISPLAY_DURATION = 5000; // Initialize the duration to 5 seconds +let CSS_ANIMATION_DURATION, + CSS_DURATION, + CSS_DELAY = 0; // Initialize the CSS variables +let BANNER; // Declare the banner variable in the outer scope + +function initializeCSSProperties(result) { + DISPLAY_DURATION = result.duration || DISPLAY_DURATION; + if (DEBUG) console.log("Duration set to:", DISPLAY_DURATION, "(in ms)"); + + // Set variables to css for delay for animation + CSS_ANIMATION_DURATION = 300 / 1000; + CSS_DURATION = DISPLAY_DURATION / 1000; + CSS_DELAY = CSS_DURATION - CSS_ANIMATION_DURATION - CSS_ANIMATION_DURATION; + + if (DEBUG) console.log("--duration:", `${CSS_ANIMATION_DURATION}s`); + if (DEBUG) console.log("--delay:", `${CSS_DURATION}s`); + + CSS_ANIMATION_DURATION = CSS_ANIMATION_DURATION + "s"; + document.body.style.setProperty("--duration", CSS_ANIMATION_DURATION); + + CSS_DELAY = CSS_DELAY + "s"; + document.body.style.setProperty("--delay", CSS_DELAY); +} + +function injectCSS() { + // Inject the CSS file + const link = document.createElement("link"); + link.href = browser.runtime.getURL("style.css"); + link.rel = "stylesheet"; + document.head.appendChild(link); + + // Return the link element + return link; +} + +function createBanner() { + // Create the banner container + const banner = document.createElement("div"); + banner.classList.add("extension-banner-container"); + + const marqeeText = "YOU ARE NOW SURFING THE WEB AS A BOT 🤖 "; + + const bannerContent = ` + + `; + + // Set the banner content + banner.innerHTML = bannerContent; + + // Append the banner to the body + document.body.appendChild(banner); + + // Return the banner + return banner; +} + +function removeBanner() { + setTimeout(() => { + if (BANNER && BANNER.parentNode) { + // Remove the banner + BANNER.parentNode.removeChild(BANNER); + if (DEBUG) console.log("Banner removed after duration."); + + // Remove the injected CSS file + const link = document.querySelector('link[href$="style.css"]'); // Match any href ending with "style.css" + link.parentNode.removeChild(link); + } + }, DISPLAY_DURATION); +} + (function () { - // Use chrome or browser depending on the environment - var browser = chrome || browser; - - // Duration to show the banner (in milliseconds) - let DISPLAY_DURATION = 5000; // Initialize the duration to 5 seconds - let banner; // Declare the banner variable in the outer scope - // Get the duration from local storage and update the DISPLAY_DURATION variable - browser.storage.local - .get(["duration", "status"]) // Fetch both duration and status + browser.storage.sync + .get(["duration", "status", "bannerInjected"]) // Fetch both duration and status .then((result) => { - DISPLAY_DURATION = result.duration || DISPLAY_DURATION; - console.log("Duration set to:", DISPLAY_DURATION, "(in ms)"); + if (DEBUG) + console.log( + "content.js reads from storage: bannerInjected =", + result.bannerInjected + ); + if (!result.bannerInjected) { + // Initialize the CSS properties + initializeCSSProperties(result); - // Set variables to css for delay for animation - let CSS_ANIMATION_DURATION = 300 / 1000; - let CSS_DURATION = DISPLAY_DURATION / 1000; - let CSS_DELAY = - CSS_DURATION - CSS_ANIMATION_DURATION - CSS_ANIMATION_DURATION; + if (result.status === 0) { + // Extension is OFF, do nothing + if (DEBUG) console.log("Extension is OFF, exiting."); + return; + } - console.log("--duration:", `${CSS_ANIMATION_DURATION}s`); - console.log("--delay:", `${CSS_DURATION}s`); + if (DEBUG) console.log("Injecting CSS..."); - CSS_ANIMATION_DURATION = CSS_ANIMATION_DURATION + "s"; - document.body.style.setProperty( - "--duration", - CSS_ANIMATION_DURATION - ); + // Inject the CSS file + injectCSS(); + if (DEBUG) console.log("CSS file injected."); - CSS_DELAY = CSS_DELAY + "s"; - document.body.style.setProperty("--delay", CSS_DELAY); - - if (result.status === 0) { - // Extension is OFF, do nothing - console.log("Extension is OFF, exiting."); - return; + // Create the banner + BANNER = createBanner(); + if (DEBUG) console.log("Banner injected:", BANNER); + } else { + // Banner has already been injected, remove the banner + if (DEBUG) + console.log("Banner already injected... removing banner."); + removeBanner(); } - - if (result.bannerInjected) { - // Banner has already been injected, do nothing - console.log("Banner already injected, exiting."); - return; - } - - console.log("Injecting the banner..."); - - // Inject the CSS file - const link = document.createElement("link"); - link.href = browser.runtime.getURL("style.css"); - link.rel = "stylesheet"; - document.head.appendChild(link); - console.log("CSS file injected."); - - // Create and style the banner container - banner = document.createElement("div"); - banner.classList.add("extension-banner-container"); - - const marqeeText = "YOU ARE NOW SURFING THE WEB AS A BOT 🤖 "; - - const bannerContent = ` - - `; - - // Set the banner content - banner.innerHTML = bannerContent; - - // Append the banner to the body - document.body.appendChild(banner); - console.log("Banner injected:", banner); - - // Set the flag in local storage to indicate that the banner was injected - return browser.storage.local.set({ bannerInjected: true }); }) .then(() => { // Remove the banner after the specified duration - setTimeout(() => { - if (banner && banner.parentNode) { - banner.parentNode.removeChild(banner); - console.log("Banner removed after duration."); - - // Reset the flag when the banner is removed - browser.storage.local.set({ bannerInjected: false }); - } - }, DISPLAY_DURATION); + removeBanner(); }) .catch((error) => { console.error("Error in content script:", error); diff --git a/1000_bots_webextension/content_chrome.js b/1000_bots_webextension/content_chrome.js new file mode 100644 index 0000000..b662b75 --- /dev/null +++ b/1000_bots_webextension/content_chrome.js @@ -0,0 +1,132 @@ +// Use chrome or browser depending on the environment +const browser = chrome || browser; + +let DEBUG; // Declare the DEBUG variable in the outer scope + +browser.storage.sync.get("debug").then((result) => { + DEBUG = result.debug; + if (DEBUG) console.log("DEBUG mode:", DEBUG); +}); + +// Duration to show the banner (in milliseconds) +let DISPLAY_DURATION = 5000; // Initialize the duration to 5 seconds +let CSS_ANIMATION_DURATION, + CSS_DURATION, + CSS_DELAY = 0; // Initialize the CSS variables +let BANNER; // Declare the banner variable in the outer scope + +function initializeCSSProperties(result) { + DISPLAY_DURATION = result.duration || DISPLAY_DURATION; + if (DEBUG) console.log("Duration set to:", DISPLAY_DURATION, "(in ms)"); + + // Set variables to css for delay for animation + CSS_ANIMATION_DURATION = 300 / 1000; + CSS_DURATION = DISPLAY_DURATION / 1000; + CSS_DELAY = CSS_DURATION - CSS_ANIMATION_DURATION - CSS_ANIMATION_DURATION; + + if (DEBUG) console.log("--duration:", `${CSS_ANIMATION_DURATION}s`); + if (DEBUG) console.log("--delay:", `${CSS_DURATION}s`); + + CSS_ANIMATION_DURATION = CSS_ANIMATION_DURATION + "s"; + document.body.style.setProperty("--duration", CSS_ANIMATION_DURATION); + + CSS_DELAY = CSS_DELAY + "s"; + document.body.style.setProperty("--delay", CSS_DELAY); +} + +function injectCSS() { + // Inject the CSS file + const link = document.createElement("link"); + link.href = browser.runtime.getURL("style.css"); + link.rel = "stylesheet"; + document.head.appendChild(link); + + // Return the link element + return link; +} + +function createBanner() { + // Create the banner container + const banner = document.createElement("div"); + banner.classList.add("extension-banner-container"); + + const marqeeText = "YOU ARE NOW SURFING THE WEB AS A BOT 🤖 "; + + const bannerContent = ` + + `; + + // Set the banner content + banner.innerHTML = bannerContent; + + // Append the banner to the body + document.body.appendChild(banner); + + // Return the banner + return banner; +} + +function removeBanner() { + setTimeout(() => { + if (BANNER && BANNER.parentNode) { + // Remove the banner + BANNER.parentNode.removeChild(BANNER); + if (DEBUG) console.log("Banner removed after duration."); + + // Remove the injected CSS file + const link = document.querySelector('link[href$="style.css"]'); // Match any href ending with "style.css" + link.parentNode.removeChild(link); + } + }, DISPLAY_DURATION); +} + +(function () { + // Get the duration from local storage and update the DISPLAY_DURATION variable + browser.storage.sync + .get(["duration", "status", "bannerInjected"]) // Fetch both duration and status + .then((result) => { + if (DEBUG) + console.log( + "content.js reads from storage: bannerInjected =", + result.bannerInjected + ); + if (!result.bannerInjected) { + // Initialize the CSS properties + initializeCSSProperties(result); + + if (result.status === 0) { + // Extension is OFF, do nothing + if (DEBUG) console.log("Extension is OFF, exiting."); + return; + } + + if (DEBUG) console.log("Injecting CSS..."); + + // Inject the CSS file + injectCSS(); + if (DEBUG) console.log("CSS file injected."); + + // Create the banner + BANNER = createBanner(); + if (DEBUG) console.log("Banner injected:", BANNER); + } else { + // Banner has already been injected, remove the banner + if (DEBUG) + console.log("Banner already injected... removing banner."); + removeBanner(); + } + }) + .then(() => { + // Remove the banner after the specified duration + removeBanner(); + }) + .catch((error) => { + console.error("Error in content script:", error); + }); +})(); diff --git a/1000_bots_webextension/content_ff.js b/1000_bots_webextension/content_ff.js new file mode 100644 index 0000000..98a13e7 --- /dev/null +++ b/1000_bots_webextension/content_ff.js @@ -0,0 +1,144 @@ +// Use chrome or browser depending on the environment +const browser = chrome || browser; + +let DEBUG; // Declare the DEBUG variable in the outer scope + +browser.storage.sync.get("debug").then((result) => { + DEBUG = result.debug; + if (DEBUG) console.log("DEBUG mode:", DEBUG); +}); + +// Duration to show the banner (in milliseconds) +let DISPLAY_DURATION = 5000; // Initialize the duration to 5 seconds +let CSS_ANIMATION_DURATION, + CSS_DURATION, + CSS_DELAY = 0; // Initialize the CSS variables +let BANNER; // Declare the banner variable in the outer scope + +function initializeCSSProperties(result) { + DISPLAY_DURATION = result.duration || DISPLAY_DURATION; + if (DEBUG) console.log("Duration set to:", DISPLAY_DURATION, "(in ms)"); + + // Set variables to css for delay for animation + CSS_ANIMATION_DURATION = 300 / 1000; + CSS_DURATION = DISPLAY_DURATION / 1000; + CSS_DELAY = CSS_DURATION - CSS_ANIMATION_DURATION - CSS_ANIMATION_DURATION; + + if (DEBUG) console.log("--duration:", `${CSS_ANIMATION_DURATION}s`); + if (DEBUG) console.log("--delay:", `${CSS_DURATION}s`); + + CSS_ANIMATION_DURATION = CSS_ANIMATION_DURATION + "s"; + document.body.style.setProperty("--duration", CSS_ANIMATION_DURATION); + + CSS_DELAY = CSS_DELAY + "s"; + document.body.style.setProperty("--delay", CSS_DELAY); +} + +function injectCSS() { + // Inject the CSS file + const link = document.createElement("link"); + link.href = browser.runtime.getURL("style.css"); + link.rel = "stylesheet"; + document.head.appendChild(link); + + // Return the link element + return link; +} + +function createBanner() { + // Create the banner container + const banner = document.createElement("div"); + banner.classList.add("extension-banner-container"); + + const marqeeText = "YOU ARE NOW SURFING THE WEB AS A BOT 🤖 "; + + const bannerContent = ` + + `; + + // Set the banner content + banner.innerHTML = bannerContent; + + // Append the banner to the body + document.body.appendChild(banner); + + // Return the banner + return banner; +} + +(function () { + // Get the duration from local storage and update the DISPLAY_DURATION variable + browser.storage.sync.get(["duration", "status"], function (result) { + // Initialize the CSS properties + initializeCSSProperties(result); + + if (result.status === 0) { + // Extension is OFF, do nothing + if (DEBUG) console.log("Extension is OFF, exiting."); + return; + } + + if (result.bannerInjected === true) { + // Banner has already been injected, do nothing + if (DEBUG) console.log("Banner already injected, exiting."); + return; + } + + if (DEBUG) console.log("Injecting CSS..."); + + // Inject the CSS file + injectCSS(); + if (DEBUG) console.log("CSS file injected."); + + // Create the banner + BANNER = createBanner(); + if (DEBUG) console.log("Banner injected:", BANNER); + + // Set the flag in local storage to indicate that the banner was injected + browser.storage.sync.set({ bannerInjected: true }, function () { + if (browser.runtime.lastError) { + console.error( + "Error setting bannerInjected flag:", + browser.runtime.lastError + ); + } else { + // Remove the banner after the specified duration + setTimeout(() => { + if (BANNER && BANNER.parentNode) { + // Remove the banner + BANNER.parentNode.removeChild(BANNER); + if (DEBUG) + console.log("Banner removed after duration."); + + // Remove the injected CSS file + const link = document.querySelector( + 'link[href="style.css"]' + ); + if (link) { + link.parentNode.removeChild(link); // Corrected to remove the link + } + + // Reset the flag when the banner is removed + browser.storage.sync.set( + { bannerInjected: false }, + function () { + if (browser.runtime.lastError) { + console.error( + "Error resetting bannerInjected flag:", + browser.runtime.lastError + ); + } + } + ); + } + }, DISPLAY_DURATION); + } + }); + }); +})(); diff --git a/1000_bots_webextension/manifest.json b/1000_bots_webextension/manifest.json index 6831b9a..46aeacc 100644 --- a/1000_bots_webextension/manifest.json +++ b/1000_bots_webextension/manifest.json @@ -1,50 +1,56 @@ { - "name": "1000 Bots", - "version": "0.0.1", - "description": "Surf the Web as Googlebot. Ever wondered what the Googlebot get’s to see online that you do not?", - "homepage_url": "http://1000scores.com/portfolio-items/mediengruppe-bitnik-1000-bots/", - "manifest_version": 3, - - "background": { - "service_worker": "background.js" - }, - - "permissions": [ - "storage", - "tabs", - "scripting", - "activeTab", - "declarativeNetRequest", - "declarativeNetRequestFeedback" - ], - - "host_permissions": ["*://*/*"], - - "action": { - "default_title": "Click to change your browser's perspective", - "default_icon": "icon_OFF_48.png" - }, - - "content_scripts": [ - { - "matches": [""], - "js": ["content.js"], - "css": ["style.css"], - "run_at": "document_idle" - } - ], - - "web_accessible_resources": [ - { - "resources": ["style.css"], - "matches": [""] - } - ], - - "browser_specific_settings": { - "gecko": { - "id": "trash@bitnik.org", - "strict_min_version": "55.0" - } - } + "name": "Refuse to be Human — Surf the Web as Googlebot", + "short_name": "Refuse to be Human", + "version": "0.0.3", + "description": "Surf the Web as Googlebot. Ever wondered what the Googlebot get’s to see online that you do not?", + "homepage_url": "http://1000scores.com/portfolio-items/mediengruppe-bitnik-1000-bots/", + "manifest_version": 3, + "background": { + "service_worker": "background.js" + }, + "permissions": [ + "storage", + "tabs", + "scripting", + "activeTab", + "declarativeNetRequest", + "declarativeNetRequestFeedback" + ], + "host_permissions": [ + "*://*/*" + ], + "action": { + "default_title": "Click to change your browser's perspective", + "default_icon": "icon_OFF_48.png" + }, + "content_scripts": [ + { + "matches": [ + "" + ], + "js": [ + "content.js" + ], + "css": [ + "style.css" + ], + "run_at": "document_idle" + } + ], + "web_accessible_resources": [ + { + "resources": [ + "style.css" + ], + "matches": [ + "" + ] + } + ], + "browser_specific_settings": { + "gecko": { + "id": "trash@bitnik.org", + "strict_min_version": "55.0" + } + } } diff --git a/1000_bots_webextension/manifest_chrome.json b/1000_bots_webextension/manifest_chrome.json new file mode 100644 index 0000000..46aeacc --- /dev/null +++ b/1000_bots_webextension/manifest_chrome.json @@ -0,0 +1,56 @@ +{ + "name": "Refuse to be Human — Surf the Web as Googlebot", + "short_name": "Refuse to be Human", + "version": "0.0.3", + "description": "Surf the Web as Googlebot. Ever wondered what the Googlebot get’s to see online that you do not?", + "homepage_url": "http://1000scores.com/portfolio-items/mediengruppe-bitnik-1000-bots/", + "manifest_version": 3, + "background": { + "service_worker": "background.js" + }, + "permissions": [ + "storage", + "tabs", + "scripting", + "activeTab", + "declarativeNetRequest", + "declarativeNetRequestFeedback" + ], + "host_permissions": [ + "*://*/*" + ], + "action": { + "default_title": "Click to change your browser's perspective", + "default_icon": "icon_OFF_48.png" + }, + "content_scripts": [ + { + "matches": [ + "" + ], + "js": [ + "content.js" + ], + "css": [ + "style.css" + ], + "run_at": "document_idle" + } + ], + "web_accessible_resources": [ + { + "resources": [ + "style.css" + ], + "matches": [ + "" + ] + } + ], + "browser_specific_settings": { + "gecko": { + "id": "trash@bitnik.org", + "strict_min_version": "55.0" + } + } +} diff --git a/1000_bots_webextension/manifest_ff.json b/1000_bots_webextension/manifest_ff.json new file mode 100644 index 0000000..fa79983 --- /dev/null +++ b/1000_bots_webextension/manifest_ff.json @@ -0,0 +1,32 @@ +{ + "homepage_url": "http://1000scores.com/portfolio-items/mediengruppe-bitnik-1000-bots/", + "name": "Refuse to be Human — Surf the Web as Googlebot", + "short_name": "Refuse to be Human", + "browser_specific_settings": { + "gecko": { + "id": "trash@bitnik.org", + "strict_min_version": "55.0" + } + }, + "description": "Surf the Web as Googlebot. Ever wondered what the Googlebot get’s to see online that you do not?", + "version": "0.0.3", + "background": { + "scripts": [ + "background.js" + ], + "persistent": true + }, + "permissions": [ + "tabs", + "activeTab", + "webRequest", + "webRequestBlocking", + "storage", + "*://*/*" + ], + "browser_action": { + "name": "Click to change your browsers perspective", + "default_icon": "icon_OFF_48.png" + }, + "manifest_version": 2 +} diff --git a/1000_bots_webextension/old.background.js b/1000_bots_webextension/old.background.js deleted file mode 100644 index 34f592f..0000000 --- a/1000_bots_webextension/old.background.js +++ /dev/null @@ -1,79 +0,0 @@ -/* - 1000 Bots - Surf the Web as Googlebot - - Copyleft (C) 2020 !Mediengruppe Bitnik, connect@bitnik.org - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -*/ - -'use strict'; - -var browser = browser || chrome -var user_agent = "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"; -var target_urls = "*://*/*"; -var status = 0; - - -function set_extension_status_ON() { - status = 1; - //console.log('Setting status to ON'); - browser.browserAction.setIcon({path: 'icon_ON_48.png'}); - browser.browserAction.setTitle({title: "1000 Bots"}); -} - -function set_extension_status_OFF() { - status = 0; - //console.log('Setting status to OFF'); - browser.browserAction.setIcon({path: 'icon_OFF_48.png'}); - browser.browserAction.setTitle({title: "1000 Bots activate"}); -} - -function update_icon(){ - if(status == 0) { - set_extension_status_ON(); - }else{ - set_extension_status_OFF(); - } -} - - -function rewrite_user_agent_header(e){ - - //console.log('Browser http request!'); - - if(status == 0) { - // console.log('Nothing to do'); - return {requestHeaders: e.requestHeaders}; - } - - for (var header of e.requestHeaders) { - if (header.name.toLowerCase() === "user-agent") { - header.value = user_agent; - } - } - //console.log('Set user-agent header to: ' + user_agent); - return {requestHeaders: e.requestHeaders}; - -} - - -browser.runtime.onStartup.addListener(set_extension_status_OFF); -browser.browserAction.onClicked.addListener(update_icon); - -browser.webRequest.onBeforeSendHeaders.addListener( - rewrite_user_agent_header, - {urls: [target_urls]}, - ["blocking", "requestHeaders"] -); diff --git a/1000_bots_webextension/old.manifest.json b/1000_bots_webextension/old.manifest.json deleted file mode 100644 index e5ff046..0000000 --- a/1000_bots_webextension/old.manifest.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "homepage_url": "http://1000scores.com/portfolio-items/mediengruppe-bitnik-1000-bots/", - "name": "1000 Bots", - "browser_specific_settings": { - "gecko": { - "id": "trash@bitnik.org", - "strict_min_version": "55.0" - } - }, - "description": "Surf the Web as Googlebot. Ever wondered what the Googlebot get’s to see online that you do not?", - "version": "0.0.1", - "background": { - "scripts": ["background.js"], - "persistent": true - }, - "permissions": ["webRequest", "webRequestBlocking", "*://*/*"], - "browser_action": { - "name": "Click to change your browsers perspective", - "default_icon": "icon_OFF_48.png" - }, - "manifest_version": 2 -} diff --git a/1000_bots_webextension/package_me.sh b/1000_bots_webextension/package_me.sh new file mode 100755 index 0000000..cab6b78 --- /dev/null +++ b/1000_bots_webextension/package_me.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +# Export folder +export_folder="packaged" + +# Name of the extension +extension_name="refused_to_be_human" + +# Files to include in the package +include_files="background.js content.js icon_OFF_48.png icon_ON_48.png manifest.json style.css" + +# Get the current version using jq to parse JSON (if jq is available) +current_version=$(jq -r '.version' manifest.json) + +# If jq is not available, fallback to a simpler grep (removing the -P flag) +# current_version=$(grep -o '"version": "[0-9.]*"' manifest_ff.json | grep -o '[0-9.]*') + +# Split version into major, minor, and patch +IFS='.' read -r major minor patch <<< "$current_version" + +# Increment the patch version by 1 +new_patch=$((patch + 1)) + +# Format the new version +new_version="$major.$minor.$new_patch" + +# Output the new version +echo "New version: $new_version" + +# Update version in manifest.json, manifest_ff.json, and manifest_chrome.json +for file in manifest.json manifest_ff.json manifest_chrome.json; do + if [ -f "$file" ]; then + # Use jq to update the version in each JSON file + jq --arg new_version "$new_version" '.version = $new_version' "$file" > tmp.json && mv tmp.json "$file" + echo "Updated $file to version $new_version" + else + echo "$file not found, skipping..." + fi +done + +# Replace version number in manifest_ff.json and chrome +sed -i "s/\"version\": \"$current_version\"/\"version\": \"$new_version\"/" manifest_ff.json +sed -i "s/\"version\": \"$current_version\"/\"version\": \"$new_version\"/" manifest_chrome.json + +folder_name="$extension_name-$new_version" + +# Create a new folder with the extension name and version inside the export folder if it doesn't exist +if [ ! -d "$export_folder/$folder_name" ]; then + mkdir -p "$export_folder/$folder_name" + echo "Created folder: $export_folder/$folder_name" +else + echo "Folder $export_folder/$folder_name already exists, skipping..." +fi + +# prepping firefox xpi +cp background_ff.js background.js +cp content_ff.js content.js +cp manifest_ff.json manifest.json +zip "$export_folder/$folder_name/$extension_name-$new_version.xpi" $include_files + +# prepping chrome file +cp background_chrome.js background.js +cp content_chrome.js content.js +cp manifest_chrome.json manifest.json +zip "$export_folder/$folder_name/$extension_name-$new_version.zip" $include_files + +# setting back to chrome manifest +cp background_chrome.js background.js +cp content_chrome.js content.js +cp manifest_chrome.json manifest.json \ No newline at end of file diff --git a/1000_bots_webextension/packaged/refused_to_be_human-0.0.2/refused_to_be_human-0.0.2.xpi b/1000_bots_webextension/packaged/refused_to_be_human-0.0.2/refused_to_be_human-0.0.2.xpi new file mode 100644 index 0000000..87c64b7 Binary files /dev/null and b/1000_bots_webextension/packaged/refused_to_be_human-0.0.2/refused_to_be_human-0.0.2.xpi differ diff --git a/1000_bots_webextension/packaged/refused_to_be_human-0.0.2/refused_to_be_human-0.0.2.zip b/1000_bots_webextension/packaged/refused_to_be_human-0.0.2/refused_to_be_human-0.0.2.zip new file mode 100644 index 0000000..0b15515 Binary files /dev/null and b/1000_bots_webextension/packaged/refused_to_be_human-0.0.2/refused_to_be_human-0.0.2.zip differ diff --git a/1000_bots_webextension/packaged/refused_to_be_human-0.0.3/refused_to_be_human-0.0.3.xpi b/1000_bots_webextension/packaged/refused_to_be_human-0.0.3/refused_to_be_human-0.0.3.xpi new file mode 100644 index 0000000..623a935 Binary files /dev/null and b/1000_bots_webextension/packaged/refused_to_be_human-0.0.3/refused_to_be_human-0.0.3.xpi differ diff --git a/1000_bots_webextension/packaged/refused_to_be_human-0.0.3/refused_to_be_human-0.0.3.zip b/1000_bots_webextension/packaged/refused_to_be_human-0.0.3/refused_to_be_human-0.0.3.zip new file mode 100644 index 0000000..4512005 Binary files /dev/null and b/1000_bots_webextension/packaged/refused_to_be_human-0.0.3/refused_to_be_human-0.0.3.zip differ