Creating Extension for Spoiler Detection

Celestial
5 min readMay 1, 2024

--

Hello my retained users, I know you have read a lot but I pray that it must not go all in vain just like your degrees.

Last blog talks about how to make an API , now this blog will tell you how to use the API in your extension but for that , first we will make the extension.

If you are new and want to know the ingredients — read here — Previous Blog

To fetch API you must run the code from the last blog and now follow me gurl!!!

To make the extension the first most thing is make a file name ‘manifest.json’ — the name must be the same as it is. Now, Let’s jump to the code.

Key Pair Value for Manifest.json file

The code describes nothing but description of your project/extension. In simple key pair value.

Instead of manifesting a career , you manifested a partner who can’t even make a project for you?? Damn !!!!!

Coming to the next file named “hide-spoiler.js” which contains the heaviest code of the extension universe. The more functionality you need , the more you are going to add the java script.

Let’s start -

// Function to send a chunk of text to the server for spoiler detection
async function sendChunkToServer(chunk) {
try {
// Send a POST request to the server at http://127.0.0.1:8000/check_spoiler
const response = await fetch('http://127.0.0.1:8000/check_spoiler', {
method: 'POST', // Using POST method
headers: {
'Content-Type': 'application/json' // Setting Content-Type header to indicate JSON data
},
body: JSON.stringify({ text: chunk }) // Sending the chunk of text as JSON data in the request body
});
// Parse the response as JSON
const data = await response.json();
// If the 'spoilers' key in the response is null, return null
if (data.spoilers === null) {
return null;
}
// Otherwise, return the spoilers array from the response
return data.spoilers;
} catch (error) {
// If an error occurs during the request, log the error and return an empty array
console.error('Error sending chunk to server:', error);
return []; // Return empty array if there's an error
}
}

// Retrieve all text from the body
var allText = document.body.innerText;

// Function to chunk text into chunks of specified size
function chunkText(text, chunkSize) {
var chunks = [];
for (var i = 0; i < text.length; i += chunkSize) {
chunks.push(text.slice(i, i + chunkSize)); // Pushing each chunk of text into the chunks array
}
return chunks;
}

// Chunk the text into chunks of 10000 characters
var textChunks = chunkText(allText, 10000);

// Array to store all spoilers detected
var spoilers_utterances = [];

// Process each chunk asynchronously
async function processChunks() {
for (const chunk of textChunks) {
// Send each chunk to the server for spoiler detection
const spoilers = await sendChunkToServer(chunk);
// If spoilers are detected and returned by the server, add them to the spoilers_utterances array
if (spoilers !== null && spoilers !== undefined && Array.isArray(spoilers)) {
spoilers_utterances.push(...spoilers);
}
}
// Log the spoilers detected
console.log(spoilers_utterances);
kw = spoilers_utterances;
tags = "SPANEMBIULOLI";
total = 0;

for (var ii = 0; ii < kw.length; ii++) {
// Escape parentheses in keyword
var escapedKeyword = kw[ii].replace(/([()])/g, "\\$1");
o = $(`*:contains(${escapedKeyword}):not(:has(:contains(${escapedKeyword})))`);
for (var i = 0; i < o.length; i++) {
if (!o[i].parentNode || o[i].parentNode.nodeName === "BODY") {
continue;
}
hideSpoiler(o[i]);
total++;
}
}

if (total >= 10) {
headings = document.querySelectorAll("h1, h2, h3, h4, h5, h6");
for (var i = 0; i < headings.length; i++) hideNode(headings[i]);
}

// Hide spoilers in the document

function hideSpoiler(node) {
ancestor = node.parentNode;
if (ancestor != null) {
if (ancestor.parentNode != null && ancestor.tagName != 'BODY')
ancestor = ancestor.parentNode;
imgs = ancestor.getElementsByTagName('img');
for (var i = 0; i < imgs.length; i++)
imgs[i].style.webkitFilter = "blur(10px)";
lists = ancestor.getElementsByTagName('li');
for (var i = 0; i < lists.length; i++) hideNode(lists[i]);
}

if (node == null || node.parentNode == null) return;
all_child = node.parentNode.children;
for (var i = 0; i < all_child.length; i++) {
var type = all_child[i].tagName;
// Use indexOf instead of match
if (tags.indexOf(type) != -1) hideNode(all_child[i]);
}
hideNode(node);
}

function hideNode(node) {
node.style.webkitFilter = "blur(10px)";
}

}



// Function to clear spoilers from the document
function clearSpoilers() {
// Show loading spinner while processing
const loadingSpinner = document.createElement('div');
loadingSpinner.textContent = 'Loading...';
loadingSpinner.style.position = 'fixed';
loadingSpinner.style.top = '50%';
loadingSpinner.style.left = '50%';
loadingSpinner.style.transform = 'translate(-50%, -50%)';
loadingSpinner.style.zIndex = '10000';
document.body.appendChild(loadingSpinner);

// Blur the background
document.body.style.filter = 'blur(5px)';

// Call processChunks() to clear spoilers asynchronously
processChunks().then(() => {
// Remove loading spinner after processing is complete
document.body.removeChild(loadingSpinner);

// Unblur the background
document.body.style.filter = 'none';
});
}

// Function to handle user input (confirmation)
function handleUserInput(isConfirmed) {
if (isConfirmed) {
// If user confirms, clear spoilers
clearSpoilers();
} else {
// If user cancels, log a message
console.log("Okay, no problem. Have a spoiler-free day!");
}
}

// Show confirmation dialog to the user
const isConfirmed = window.confirm("Do you want to clear the spoilers on this page?");
// Handle user input based on confirmation
handleUserInput(isConfirmed);

And that’s the code babe/dude ,

The next simple steps is to load your extension to actually your chrome -

So follow me to link — chrome://extensions/

Now after landing to this page enable the developers mode despite you aren’t the one -

Developer mode

Then what click on the load unpack -

And load your file which contain all of these -

  • The other java script file link is — jquery
  • The icon can be anything png file of your desire

And yes you are good to go to use your extension — just remember you must run your Fast Api file.

Will see you next time , my dear reader.

--

--

Celestial
Celestial

Written by Celestial

Uncovering Patterns , Empowering Strategies.

No responses yet