Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add htmlBlockingStrategy to remove dependency on youtubeDataAPIBlockingStrategy #4

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions docs/Oscar_Semecs_suggestion.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// ==UserScript==
// @name Youtube Blocker
// @namespace http://tampermonkey.net/
// @version 0.1
// @description try to take over the world!
// @author You
// @match https://www.youtube.com/*
// @icon https://www.google.com/s2/favicons?domain=youtube.com
// @grant none
// ==/UserScript==

(function() {


var curUrl = window.location.href;

window.setInterval(function(){
if(curUrl != window.location.href) {
curUrl = window.location.href;

setTimeout(function(){
checkUrl();
}, 1000);


}
}, 10);
checkUrl();


function checkUrl(){
var scripts = document.scripts;
for(index in scripts) {
if(typeof scripts[index].innerHTML !== "undefined" && scripts[index].innerHTML.indexOf('"category":') !== -1) {
pos = scripts[index].innerHTML.indexOf('"category":');
tmp = scripts[index].innerHTML.substring(pos+12,pos+100);
pos = tmp.indexOf('"');

tmp = tmp.substring(0,pos);
if(tmp != "Education" && tmp.substring(0,5) != "Howto") {
window.location.replace("https://www.youtube.com");
}
break;
}

if(typeof scripts[index].innerHTML !== "undefined" && scripts[index].innerHTML.indexOf('"genre":') !== -1) {
pos = scripts[index].innerHTML.indexOf('"genre":');
tmp = scripts[index].innerHTML.substring(pos+9,pos+100);
pos = tmp.indexOf('"');
tmp = tmp.substring(0,pos);
if(tmp != "Education" && tmp.substring(0,5) != "Howto") {
window.location.replace("https://www.youtube.com");
}
break;
}

}

}


})();
41 changes: 2 additions & 39 deletions js/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,7 @@ let harderDeactivateClicksVal;

$(document).ready(function() {

function initialSetupjQuery() {
$('#startButton').hide();
$('#text').hide();
clearWarningTextjQuery();
$("#options").text("Set your YouTube key to start blocking");
$('#harderDeactivateText').hide()
$('#harderDeactivate').hide()
}

chrome.storage.local.get('apiKey', function(data) {
if (data.apiKey === undefined) {
initialSetupjQuery();
}
else {
$('#harderDeactivateDiv').show()
if (data.apiKey == "") {
console.log('trigger empty key')
USER_API_KEY = DEFAULT_API_KEY;
warningTextjQuery()
}
else {
clearWarningTextjQuery();
console.log('---------------- API Key:' + data.apiKey + " ----------------")
USER_API_KEY = data.apiKey
}
}

})
$('#harderDeactivateDiv').show()


// notifiy content script when youtube dynamically updates DOM to prevent re fetching API
Expand Down Expand Up @@ -120,7 +93,7 @@ chrome.runtime.onMessage.addListener(
function showNotification(message) {
let options = {
type: 'basic',
iconUrl: '../resources/icon.png',
iconUrl: '../resources/icon.png',
title: "Youtube Blocker",
message: message,
}
Expand Down Expand Up @@ -347,14 +320,4 @@ chrome.runtime.onMessage.addListener(
$('#harderDeactivate').show()
}

function warningTextjQuery() {
$("#warning").show();
$('body').css({'height':'390px'});
}

function clearWarningTextjQuery() {
$("#warning").hide();
$('body').css({'height':'360px'});
}

});
145 changes: 78 additions & 67 deletions js/contentScript.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,14 @@

let firstRun = false;
let prevUrls = [];
let previousvideoMetaData = [];
let activated;
const youtubeCategoryMappings = {
"1": "Film & Animation",
"2": "Autos & Vehicles",
"10": "Music",
"15": "Pets & Animals",
"17": "Sports",
"18": "Short Movies",
"19": "Travel & Events",
"20": "Gaming",
"21": "Videoblogging",
"22": "People & Blogs",
"23": "Comedy",
"24": "Entertainment",
"25": "News & Politics",
"26": "Howto & Style",
"27": "Education",
"28": "Science & Technology",
"29": "Nonprofits & Activism",
"30": "Movies",
"31": "Anime/Animation",
"32": "Action/Adventure",
"33": "Classics",
"34": "Comedy",
"35": "Documentary",
"36": "Drama",
"37": "Family",
"38": "Foreign",
"39": "Horror",
"40": "Sci-Fi/Fantasy",
"41": "Thriller",
"42": "Shorts",
"43": "Shows",
"44": "Trailers"
}
const allowedVideoCategories = ["Howto & Style", "Education", "Science & Technology"]

chrome.storage.local.get(['activated'], function(data) {
activated = data.activated;
console.log('Activated value: ' + activated)

if (activated == true) {
console.log('Blocking is activated. Initiating blocking')
initiate();
initiateBlockingBasedOnInnerHtml();
}
else {
console.log('Blocking not activated. Not initiating')
Expand All @@ -54,52 +19,96 @@ chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.query === 'Page updated')
{
console.log('Page updated');
initiate();
initiateBlockingBasedOnInnerHtml();
}
});

function initiate() {
let currentUrl = location.href;
if (prevUrls.includes(currentUrl)) {
console.log('--------- Url already fetched.Not fetching again. ---------')
return;
}
prevUrls.push(currentUrl);
console.log("Initiating Youtube Study for new url: " + currentUrl);

chrome.runtime.sendMessage({url: currentUrl}, function(response) {
console.log("-------Response from send url message: -----------");
processYoutubeData(response.json, blockYoutubeUrl)
});

function initiateBlockingBasedOnInnerHtml() {
console.log("initiating BlockingBasedOnInnerHtml")
var curUrl = window.location.href;
window.setInterval(function(){
console.log("Checking url")
if(curUrl != window.location.href) {
curUrl = window.location.href;

setTimeout(function(){
checkUrl();
}, 1000);
}
}, 60000);
checkUrl();
}

function processYoutubeData(json, callbackBlockYoutubeUrl) {
const allowedIds = ['26', '27', '28']; // video category ids for Howto & Style, Education, Science & technology
let videoCategory = json.items[0].snippet.categoryId;
let videoCategoryString = youtubeCategoryMappings[videoCategory];
console.log("YouTube Video Category: " + videoCategoryString);
function checkUrl(){
console.log("--- inside checkUrl ---")
let scripts = document.scripts;
console.log(scripts)
for(index in scripts) {
if(typeof scripts[index].innerHTML !== "undefined" && scripts[index].innerHTML.indexOf('"category":') !== -1) {
if (handleVideoMetaData(scripts, '"category":', 12, 100)) {
break;
}
}
if(typeof scripts[index].innerHTML !== "undefined" && scripts[index].innerHTML.indexOf('"genre":') !== -1) {
if (handleVideoMetaData(scripts, '"genre":', 9, 100)) {
break;
}
}
}
// handleNoWayToCheckVideoCategoryError()
}

let isAllowedResult = allowedIds.includes(videoCategory);
function handleNoWayToCheckVideoCategoryError() {
alert("Error: Youtube Blocker could not detect the video category of this video.")
}

console.log('isAllowedUrl: ' + isAllowedResult);
if(isAllowedResult == false) {
callbackBlockYoutubeUrl(videoCategoryString);
function handleVideoMetaData(scripts, videoMetadataHtmlStartStr, startOffset, endOffset) {
pos = scripts[index].innerHTML.indexOf(videoMetadataHtmlStartStr);
videoMetadata = scripts[index].innerHTML.substring(pos + startOffset, pos + endOffset);
if (isVideoMetadataDuplicate(videoMetadata)) {
return false;
}
}
console.log(`videoMetadata for ${videoMetadataHtmlStartStr}: ` + videoMetadata)
pos = videoMetadata.indexOf('"');
videoCategory = videoMetadata.substring(0,pos);
videoCategory = videoCategory.replace("\\u0026", "&")
console.log('Youtube Video category is: ' + videoCategory)
handleYoutubeBlocking(videoCategory)
return true;
}

function isVideoMetadataDuplicate(videoMetadata) {
console.log("previousvideoMetaData: " + previousvideoMetaData)
if (previousvideoMetaData.includes(videoMetadata)) {
console.log("video meta data is duplicate")
return true;
}
console.log("video meta data is NOT duplicate")
previousvideoMetaData.push(videoMetadata);
return false;
}

function blockYoutubeUrl(videoCategoryString) {
console.log('in blockYoutubeUrl')
function handleYoutubeBlocking(videoCategoryString) {
isVideoCategoryAllowed = allowedVideoCategories.includes(videoCategoryString)
console.log("isVideoCategoryAllowed: " + isVideoCategoryAllowed)
if (isVideoCategoryAllowed == false) {
blockYoutubeVideo(videoCategoryString)
}
return true;
}

function blockYoutubeVideo(videoCategoryString) {
console.log('in blockYoutubeVideo')
chrome.storage.local.get(['activated'], function(data) {
console.log('Blocking Activated value: ' + data.activated)

if (data.activated === true) {
console.log('---- Sent create notification to background ----');
// Block redirecting happens here
location.replace('http://youtube.com')
//location.replace('http://youtube.com')
chrome.runtime.sendMessage({createNotification: true, videoCategoryString: videoCategoryString},
function(response) {
});
});
}
});
}
Expand All @@ -108,3 +117,5 @@ function blockYoutubeUrl(videoCategoryString) {





2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "YouTube Blocker",
"version": "3.4",
"version": "4.0",
"manifest_version": 2,
"description": "Block non educational YouTube videos",
"icons": {
Expand Down
46 changes: 5 additions & 41 deletions pages/options.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,55 +8,19 @@
<link rel="stylesheet" type="text/css" href="../css/optionsStyle.css">
<link rel="stylesheet" href="../bootstrap/bootstrap.min.css">
</head>
<body class="container">
<body class="container">
<h2>Youtube Blocker Setup</h2>
<p>You must create your personal free Youtube Data Key so the extension knows what videos to block using that key.
<br> You do not have to set any payment method.
</p>
<h3>Setup (6-10 minutes)</h3>
<ol>
<li>Go to <a href="https://cloud.google.com/">Google's Cloud Platform (GCP)</a> and create a free account using your google account</li>
<li>Create a new project and name it something like "Personal Youtube Data Project"</li>
<li>Click the left top navigation menu and go to <b>'APIs and Services'</b> </li>
<li>You should be on your dashboard now. Click 'Enable APIs and Services', search for Youtube Data API v3, click it, and enable it.
You should see a checkmark with 'API Enabled'
<ul>
<li>If you don't see that, then click 'Manage' and enable it on the Youtube Data Dashboard</li>
<li>Please submit an issue on the chrome extension store's 'Support' tab if you have trouble and I will assist you.</li>
</ul>
</li>
<li>Go back to 'APIs and Services'</li>
<li>Click credentials in the left hand menu and click 'Create Credentials' on the page then click API key in the drop down</li>
<li>You will see your API Key below with a number and a warning symbol. Click the Api Key you created e.g. API Key 1</li>
<li><b>Very Important:</b> Click 'Restrict Key' and select 'Youtube Data API v3'.
<br>This is to limit your key usage to the Youtube Data quota of 10k/day and prevent others from using your key
<ul>
<li>Your 'API Key 1' should now have a checkmark to its left on the 'Credentials' page</li>
</ul>
</li>
<li>Copy and paste your new personal API key in the input below to register it to the extension. It will be a long text key like this: <b>AIzaSyAeebo7DlkB6YyCem51Lq9AOAmFG</b></li>
<li>Set your API key then press the Activate button on the extension.
Refresh the video if it doesn't work right away. Double check your key is correct if doesn't work after 5 refreshes.
</li>
<li>Note: You do NOT have to set any payment method. If you did, then you can remove it since YouTube Data doesn't cost any money</li>
</ol>

<label>
<b>Input your key below</b>
<br>
<input type="text" id="API_KEY" required>
</label>
<button class="btn btn-primary" id="saveKey">Save</button>

<p id="currKey"><u>Your current Youtube Key is: </u></p>
<p>From v3.4 to the new v4.0, you no longer need to setup a Youtube Data API Key to block thanks to Oscar Semec's code changes.</p>
<h2>Options</h2>
<form id="myForm">
<h4>Click __ times to deactivate YouTube blocking</h4>
<input type="radio" id="harder10" name="clicksRadio" value="10"> 10<br>
<input type="radio" id="harder20" name="clicksRadio" value="20"> 20<br>
<input type="radio" id="harder30" name="clicksRadio" value="30"> 30<br>
<input type="radio" id="harder40" name="clicksRadio" value="40"> 40<br>
<input type="radio" id="harder50" name="clicksRadio" value="50"> 50<br>
<input type="radio" id="harder100" name="clicksRadio" value="100"> 100<br>
<button class="btn btn-primary" id="saveHarderClicks">Save</button>
</form>
</body>
</body>
</html>
3 changes: 1 addition & 2 deletions pages/popup.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="utf-8">
<title>YouTube Blocker</title>
<script src="../js/jquery-3.4.1.min.js"></script>
<script src="../js/background.js"></script>
<script src="../js/background.js" type="module"></script>
<script src="../css/bootstrap/bootstrap.min.js"></script>
<link rel="stylesheet" href="../bootstrap/bootstrap.min.css">
<link href="https://fonts.googleapis.com/css?family=Roboto:300" rel="stylesheet">
Expand All @@ -30,7 +30,6 @@ <h2>YouTube Blocker</h2>
</div>

<div>
<strong id="warning">You do not have a key set. Please set one in the options page.</strong>
<button id="options" class="btn btn-dark">Options</button>
</div>

Expand Down