From 2aa755eeb6d3e535f60ccd70e2682e3310a24f91 Mon Sep 17 00:00:00 2001 From: yoNico21 <119441054+yoNico21@users.noreply.github.com> Date: Wed, 25 Sep 2024 16:12:21 +0200 Subject: [PATCH] upgraded 1000 bots to manifest v3, added visual element to when the extension is turned on --- 1000_bots_webextension/background.js | 281 +++++++++++++++++++---- 1000_bots_webextension/content.js | 96 ++++++++ 1000_bots_webextension/manifest.json | 68 ++++-- 1000_bots_webextension/old.background.js | 79 +++++++ 1000_bots_webextension/old.manifest.json | 22 ++ 1000_bots_webextension/style.css | 171 ++++++++++++++ 6 files changed, 655 insertions(+), 62 deletions(-) create mode 100644 1000_bots_webextension/content.js create mode 100644 1000_bots_webextension/old.background.js create mode 100644 1000_bots_webextension/old.manifest.json create mode 100644 1000_bots_webextension/style.css diff --git a/1000_bots_webextension/background.js b/1000_bots_webextension/background.js index 34f592f..b0ecc22 100644 --- a/1000_bots_webextension/background.js +++ b/1000_bots_webextension/background.js @@ -18,62 +18,259 @@ */ -'use strict'; +"use strict"; -var browser = browser || chrome -var user_agent = "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"; +// Use chrome or browser depending on the environment +var browser = chrome || browser; + +// Custom user-agent to spoof Googlebot +var user_agent = + "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"; var target_urls = "*://*/*"; -var status = 0; +// Duration to display the injected HTML (in milliseconds) +const DISPLAY_DURATION = 8000; // Set to 8 seconds +// Initialize storage for duration +browser.storage.local + .set({ duration: DISPLAY_DURATION }) + .then(() => { + 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() { - status = 1; - //console.log('Setting status to ON'); - browser.browserAction.setIcon({path: 'icon_ON_48.png'}); - browser.browserAction.setTitle({title: "1000 Bots"}); + browser.storage.local + .set({ status: 1 }) + .then(() => { + console.log("Extension status set to ON"); + return browser.action.setIcon({ path: "icon_ON_48.png" }); + }) + .then(() => { + return browser.action.setTitle({ title: "1000 Bots" }); + }) + .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() { - status = 0; - //console.log('Setting status to OFF'); - browser.browserAction.setIcon({path: 'icon_OFF_48.png'}); - browser.browserAction.setTitle({title: "1000 Bots activate"}); + browser.storage.local + .set({ status: 0 }) + .then(() => { + 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" }); + }) + .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); + }); } -function update_icon(){ - if(status == 0) { - set_extension_status_ON(); - }else{ - set_extension_status_OFF(); - } +// Toggle the icon between ON and OFF +function update_icon() { + browser.storage.local + .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"], + }, + }, + ]; -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}; - + // Add the rules + return browser.declarativeNetRequest + .updateDynamicRules({ + addRules: rules, + removeRuleIds: [], + }) + .then(() => { + 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(() => { + console.log("User-Agent spoofing rules removed successfully."); + }) + .then(() => { + // Clear the bannerInjected flag when stopping the extension + return browser.storage.local.set({ bannerInjected: false }); + }) + .catch((error) => { + console.error("Error removing rules:", error); + }); +} -browser.runtime.onStartup.addListener(set_extension_status_OFF); -browser.browserAction.onClicked.addListener(update_icon); +// Function to refresh all active tabs +function refreshAllTabs() { + return browser.tabs.query({}).then((tabs) => { + tabs.forEach((tab) => { + browser.tabs + .reload(tab.id) + .then(() => { + console.log(`Refreshed tab: ${tab.id}`); + }) + .catch((error) => { + console.error(`Error refreshing tab ${tab.id}:`, error); + }); + }); + }); +} -browser.webRequest.onBeforeSendHeaders.addListener( - rewrite_user_agent_header, - {urls: [target_urls]}, - ["blocking", "requestHeaders"] -); +// Inject the content.js script into all active tabs +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(() => { + console.log( + `Content script injected into tab ${tab.id}` + ); + }) + .catch((error) => { + console.error( + `Error injecting content script into tab ${tab.id}:`, + error + ); + }); + } else { + console.log( + `Skipped injecting content script into tab ${tab.id} (chrome:// URL)` + ); + } + }) + ); + }) + .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("chrome://")) { + browser.scripting + .executeScript({ + target: { tabId: tab.id }, + function: () => { + const banner = + document.querySelector(".extension-banner"); + if (banner && banner.parentNode) { + banner.parentNode.removeChild(banner); + } + }, + }) + .then(() => { + console.log( + `Removed injected content from tab ${tab.id}` + ); + }) + .catch((error) => { + console.error( + `Error removing injected content from tab ${tab.id}:`, + error + ); + }); + } else { + console.log( + `Skipped removing injected content from tab ${tab.id} (chrome:// URL)` + ); + } + }); + }) + .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/content.js b/1000_bots_webextension/content.js new file mode 100644 index 0000000..0e72239 --- /dev/null +++ b/1000_bots_webextension/content.js @@ -0,0 +1,96 @@ +(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 + .then((result) => { + DISPLAY_DURATION = result.duration || DISPLAY_DURATION; + console.log("Duration set to:", DISPLAY_DURATION, "(in ms)"); + + // 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; + + console.log("--duration:", `${CSS_ANIMATION_DURATION}s`); + 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); + + if (result.status === 0) { + // Extension is OFF, do nothing + console.log("Extension is OFF, exiting."); + return; + } + + 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); + }) + .catch((error) => { + console.error("Error in content script:", error); + }); +})(); diff --git a/1000_bots_webextension/manifest.json b/1000_bots_webextension/manifest.json index e5ff046..6831b9a 100644 --- a/1000_bots_webextension/manifest.json +++ b/1000_bots_webextension/manifest.json @@ -1,22 +1,50 @@ { - "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 + "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": ["