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 = `
+
+
+
+ ${new Array(30).fill(marqeeText).join("")}
+
+
+
+ `;
+
+ // 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 = `
-
-
-
- ${new Array(30).fill(marqeeText).join("")}
-
-
-
- `;
-
- // 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 = `
+
+
+
+ ${new Array(30).fill(marqeeText).join("")}
+
+
+
+ `;
+
+ // 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 = `
+
+
+
+ ${new Array(30).fill(marqeeText).join("")}
+
+
+
+ `;
+
+ // 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