working extension for chrome (Manifest V3) and Firefox (Manifest V2) + created a package_me.sh for packaging the extensions for both platforms

This commit is contained in:
yoNico21 2024-10-17 14:25:16 +02:00
parent 2aa755eeb6
commit 3999bb29f9
16 changed files with 1205 additions and 275 deletions

View File

@ -20,22 +20,24 @@
"use strict"; "use strict";
const DEBUG = false;
// Use chrome or browser depending on the environment // Use chrome or browser depending on the environment
var browser = chrome || browser; const browser = chrome || browser;
// Custom user-agent to spoof Googlebot // 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)"; "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) // Duration to display the injected HTML (in milliseconds)
const DISPLAY_DURATION = 8000; // Set to 8 seconds const DISPLAY_DURATION = 8000; // Set to 8 seconds
// Initialize storage for duration // Initialize storage for duration
browser.storage.local browser.storage.sync
.set({ duration: DISPLAY_DURATION }) .set({ duration: DISPLAY_DURATION })
.then(() => { .then(() => {
console.log("Duration set to:", DISPLAY_DURATION); if (DEBUG) console.log("Duration set to:", DISPLAY_DURATION);
}) })
.catch((error) => { .catch((error) => {
console.error("Error setting duration:", error); console.error("Error setting duration:", error);
@ -43,14 +45,16 @@ browser.storage.local
// Set extension status to ON // Set extension status to ON
function set_extension_status_ON() { function set_extension_status_ON() {
browser.storage.local browser.storage.sync
.set({ status: 1 }) .set({ status: 1, bannerInjected: false, debug: DEBUG })
.then(() => { .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" }); return browser.action.setIcon({ path: "icon_ON_48.png" });
}) })
.then(() => { .then(() => {
return browser.action.setTitle({ title: "1000 Bots" }); return browser.action.setTitle({
title: "You are now surfing the web as a bot 🤖",
});
}) })
.then(() => { .then(() => {
// Start user-agent spoofing // Start user-agent spoofing
@ -71,14 +75,16 @@ function set_extension_status_ON() {
// Set extension status to OFF // Set extension status to OFF
function set_extension_status_OFF() { function set_extension_status_OFF() {
browser.storage.local browser.storage.sync
.set({ status: 0 }) .set({ status: 0 })
.then(() => { .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" }); return browser.action.setIcon({ path: "icon_OFF_48.png" });
}) })
.then(() => { .then(() => {
return browser.action.setTitle({ title: "1000 Bots activate" }); return browser.action.setTitle({
title: "Click here to refuse to be human 🤖",
});
}) })
.then(() => { .then(() => {
// Remove the content from all active tabs // Remove the content from all active tabs
@ -99,7 +105,7 @@ function set_extension_status_OFF() {
// Toggle the icon between ON and OFF // Toggle the icon between ON and OFF
function update_icon() { function update_icon() {
browser.storage.local browser.storage.sync
.get("status") .get("status")
.then((result) => { .then((result) => {
if (result.status === 0) { if (result.status === 0) {
@ -143,7 +149,10 @@ function startUserAgentSpoofing() {
removeRuleIds: [], removeRuleIds: [],
}) })
.then(() => { .then(() => {
return console.log("User-Agent spoofing rules added successfully."); if (DEBUG)
return console.log(
"User-Agent spoofing rules added successfully."
);
}) })
.then(() => {}) .then(() => {})
.catch((error) => { .catch((error) => {
@ -158,11 +167,12 @@ function stopUserAgentSpoofing() {
removeRuleIds: [1], removeRuleIds: [1],
}) })
.then(() => { .then(() => {
console.log("User-Agent spoofing rules removed successfully."); if (DEBUG)
console.log("User-Agent spoofing rules removed successfully.");
}) })
.then(() => { .then(() => {
// Clear the bannerInjected flag when stopping the extension // Clear the bannerInjected flag when stopping the extension
return browser.storage.local.set({ bannerInjected: false }); return browser.storage.sync.set({ bannerInjected: false });
}) })
.catch((error) => { .catch((error) => {
console.error("Error removing rules:", error); console.error("Error removing rules:", error);
@ -176,7 +186,7 @@ function refreshAllTabs() {
browser.tabs browser.tabs
.reload(tab.id) .reload(tab.id)
.then(() => { .then(() => {
console.log(`Refreshed tab: ${tab.id}`); if (DEBUG) console.log(`Refreshed tab: ${tab.id}`);
}) })
.catch((error) => { .catch((error) => {
console.error(`Error refreshing tab ${tab.id}:`, error); console.error(`Error refreshing tab ${tab.id}:`, error);
@ -190,33 +200,57 @@ function injectContentScript() {
return browser.tabs return browser.tabs
.query({}) .query({})
.then((tabs) => { .then((tabs) => {
return Promise.all( // Create an array of promises for each tab
tabs.map((tab) => { const promises = tabs.map((tab) => {
// Check if the tab is not a chrome URL // Check if the URL is not something like chrome:// or about:// etc.
if (!tab.url.startsWith("chrome://")) { if (tab.url.startsWith("https://")) {
return browser.scripting return browser.scripting
.executeScript({ .executeScript({
target: { tabId: tab.id }, target: { tabId: tab.id },
files: ["content.js"], files: ["content.js"],
}) })
.then(() => { .then(() => {
if (DEBUG)
console.log( console.log(
`Content script injected into tab ${tab.id}` `Content script injected into tab ${tab.id}`
); );
})
.catch((error) => { // Use a hardcoded duration for removal
console.error( const duration = 80000; // 8 seconds or whatever you need
`Error injecting content script into tab ${tab.id}:`,
error // Set a timeout to remove the content after the hardcoded duration
); setTimeout(() => {
}); browser.storage.sync.set({
} else { 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( 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) => { .catch((error) => {
console.error("Error querying tabs:", error); console.error("Error querying tabs:", error);
@ -229,7 +263,7 @@ function removeInjectedContent() {
.query({}) .query({})
.then((tabs) => { .then((tabs) => {
tabs.forEach((tab) => { tabs.forEach((tab) => {
if (!tab.url.startsWith("chrome://")) { if (tab.url.startsWith("https://")) {
browser.scripting browser.scripting
.executeScript({ .executeScript({
target: { tabId: tab.id }, target: { tabId: tab.id },
@ -242,9 +276,10 @@ function removeInjectedContent() {
}, },
}) })
.then(() => { .then(() => {
console.log( if (DEBUG)
`Removed injected content from tab ${tab.id}` console.log(
); `Removed injected content from tab ${tab.id}`
);
}) })
.catch((error) => { .catch((error) => {
console.error( console.error(
@ -253,9 +288,10 @@ function removeInjectedContent() {
); );
}); });
} else { } else {
console.log( if (DEBUG)
`Skipped removing injected content from tab ${tab.id} (chrome:// URL)` console.log(
); `Skipped removing injected content from tab ${tab.id} (chrome://, about:// URL or similar)`
);
} }
}); });
}) })

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
"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);

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
"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"]
);

View File

@ -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 = `
<div class="banner montserrat">
<div class="marquee">
<span class="marquee__inner" style="--ad: 80s;">
${new Array(30).fill(marqeeText).join("")}
</span>
</div>
</div>
`;
// 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 () { (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 // Get the duration from local storage and update the DISPLAY_DURATION variable
browser.storage.local browser.storage.sync
.get(["duration", "status"]) // Fetch both duration and status .get(["duration", "status", "bannerInjected"]) // Fetch both duration and status
.then((result) => { .then((result) => {
DISPLAY_DURATION = result.duration || DISPLAY_DURATION; if (DEBUG)
console.log("Duration set to:", DISPLAY_DURATION, "(in ms)"); 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 if (result.status === 0) {
let CSS_ANIMATION_DURATION = 300 / 1000; // Extension is OFF, do nothing
let CSS_DURATION = DISPLAY_DURATION / 1000; if (DEBUG) console.log("Extension is OFF, exiting.");
let CSS_DELAY = return;
CSS_DURATION - CSS_ANIMATION_DURATION - CSS_ANIMATION_DURATION; }
console.log("--duration:", `${CSS_ANIMATION_DURATION}s`); if (DEBUG) console.log("Injecting CSS...");
console.log("--delay:", `${CSS_DURATION}s`);
CSS_ANIMATION_DURATION = CSS_ANIMATION_DURATION + "s"; // Inject the CSS file
document.body.style.setProperty( injectCSS();
"--duration", if (DEBUG) console.log("CSS file injected.");
CSS_ANIMATION_DURATION
);
CSS_DELAY = CSS_DELAY + "s"; // Create the banner
document.body.style.setProperty("--delay", CSS_DELAY); BANNER = createBanner();
if (DEBUG) console.log("Banner injected:", BANNER);
if (result.status === 0) { } else {
// Extension is OFF, do nothing // Banner has already been injected, remove the banner
console.log("Extension is OFF, exiting."); if (DEBUG)
return; 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 = `
<div class="banner montserrat">
<div class="marquee">
<span class="marquee__inner" style="--ad: 80s;">
${new Array(30).fill(marqeeText).join("")}
</span>
</div>
</div>
`;
// 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(() => { .then(() => {
// Remove the banner after the specified duration // Remove the banner after the specified duration
setTimeout(() => { removeBanner();
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) => { .catch((error) => {
console.error("Error in content script:", error); console.error("Error in content script:", error);

View File

@ -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 = `
<div class="banner montserrat">
<div class="marquee">
<span class="marquee__inner" style="--ad: 80s;">
${new Array(30).fill(marqeeText).join("")}
</span>
</div>
</div>
`;
// 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);
});
})();

View File

@ -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 = `
<div class="banner montserrat">
<div class="marquee">
<span class="marquee__inner" style="--ad: 80s;">
${new Array(30).fill(marqeeText).join("")}
</span>
</div>
</div>
`;
// 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);
}
});
});
})();

View File

@ -1,50 +1,56 @@
{ {
"name": "1000 Bots", "name": "Refuse to be Human — Surf the Web as Googlebot",
"version": "0.0.1", "short_name": "Refuse to be Human",
"description": "Surf the Web as Googlebot. Ever wondered what the Googlebot gets to see online that you do not?", "version": "0.0.3",
"homepage_url": "http://1000scores.com/portfolio-items/mediengruppe-bitnik-1000-bots/", "description": "Surf the Web as Googlebot. Ever wondered what the Googlebot gets to see online that you do not?",
"manifest_version": 3, "homepage_url": "http://1000scores.com/portfolio-items/mediengruppe-bitnik-1000-bots/",
"manifest_version": 3,
"background": { "background": {
"service_worker": "background.js" "service_worker": "background.js"
}, },
"permissions": [
"permissions": [ "storage",
"storage", "tabs",
"tabs", "scripting",
"scripting", "activeTab",
"activeTab", "declarativeNetRequest",
"declarativeNetRequest", "declarativeNetRequestFeedback"
"declarativeNetRequestFeedback" ],
], "host_permissions": [
"*://*/*"
"host_permissions": ["*://*/*"], ],
"action": {
"action": { "default_title": "Click to change your browser's perspective",
"default_title": "Click to change your browser's perspective", "default_icon": "icon_OFF_48.png"
"default_icon": "icon_OFF_48.png" },
}, "content_scripts": [
{
"content_scripts": [ "matches": [
{ "<all_urls>"
"matches": ["<all_urls>"], ],
"js": ["content.js"], "js": [
"css": ["style.css"], "content.js"
"run_at": "document_idle" ],
} "css": [
], "style.css"
],
"web_accessible_resources": [ "run_at": "document_idle"
{ }
"resources": ["style.css"], ],
"matches": ["<all_urls>"] "web_accessible_resources": [
} {
], "resources": [
"style.css"
"browser_specific_settings": { ],
"gecko": { "matches": [
"id": "trash@bitnik.org", "<all_urls>"
"strict_min_version": "55.0" ]
} }
} ],
"browser_specific_settings": {
"gecko": {
"id": "trash@bitnik.org",
"strict_min_version": "55.0"
}
}
} }

View File

@ -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 gets 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": [
"<all_urls>"
],
"js": [
"content.js"
],
"css": [
"style.css"
],
"run_at": "document_idle"
}
],
"web_accessible_resources": [
{
"resources": [
"style.css"
],
"matches": [
"<all_urls>"
]
}
],
"browser_specific_settings": {
"gecko": {
"id": "trash@bitnik.org",
"strict_min_version": "55.0"
}
}
}

View File

@ -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 gets 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
}

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
'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"]
);

View File

@ -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 gets 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
}

View File

@ -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