initial commit
This commit is contained in:
commit
a2fced0b73
9 changed files with 529 additions and 0 deletions
26
background.js
Normal file
26
background.js
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
var token = ""
|
||||||
|
var userId = ""
|
||||||
|
var videoId = ""
|
||||||
|
|
||||||
|
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
|
||||||
|
if (request.tokenWithUrl != null) {
|
||||||
|
token = request.tokenWithUrl.replace("https://www.youtube.com/deleteallcomments#access_token=", "").replace(/&.*/g, "")
|
||||||
|
|
||||||
|
let url = chrome.runtime.getURL("deleting.html");
|
||||||
|
chrome.tabs.remove(sender.tab.id);
|
||||||
|
chrome.tabs.create({url});
|
||||||
|
} else if (request.toDeleteUserId != null) {
|
||||||
|
userId = request.toDeleteUserId.replace("https://www.youtube.com/channel/", "");
|
||||||
|
} else if (request.videoUrl != null) {
|
||||||
|
videoId = request.videoUrl.replace("https://www.youtube.com/watch?v=", "").replace(/&.*/g, "");
|
||||||
|
} else if (request.closeMe != null) {
|
||||||
|
chrome.tabs.remove(sender.tab.id);
|
||||||
|
} else {
|
||||||
|
sendResponse({
|
||||||
|
youtubetoken: token,
|
||||||
|
toDeleteUserId: userId,
|
||||||
|
videoId: videoId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
3
content-styles.css
Normal file
3
content-styles.css
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
.custom-youtube-button-class {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
69
content.js
Normal file
69
content.js
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
let observer = new MutationObserver((mutations) => { // observe changes on the page, comments are loaded separately so we need this to wait for them
|
||||||
|
mutations.forEach((mutation) => {
|
||||||
|
if (!mutation.addedNodes) return
|
||||||
|
|
||||||
|
for (let i = 0; i < mutation.addedNodes.length; i++) {
|
||||||
|
let node = mutation.addedNodes[i];
|
||||||
|
|
||||||
|
if (node.id == "reply-dialog") { // we find the reply-dialog place holder
|
||||||
|
for (let j = 0; j < node.parentElement.childElementCount; j++) {
|
||||||
|
let possibleToolbar = node.parentElement.children[j];
|
||||||
|
if (possibleToolbar.id == "toolbar") { // let's find the heath/reply toolbar
|
||||||
|
var spanTag = createDeleteAllCommentsCTA();
|
||||||
|
possibleToolbar.appendChild(spanTag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
function createDeleteAllCommentsCTA() {
|
||||||
|
var spanTag = document.createElement("span");
|
||||||
|
spanTag.setAttribute( 'class', 'custom-youtube-button-class' );
|
||||||
|
spanTag.innerHTML = "DELETE All COMMENTS"
|
||||||
|
spanTag.style.font = "12px arial,serif";
|
||||||
|
spanTag.addEventListener("click", deleteAllButtonClicked);
|
||||||
|
return spanTag
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteAllButtonClicked(pointerEvent) {
|
||||||
|
searchingCommentParent = findMainParentOfReplyCTA(pointerEvent)
|
||||||
|
var referenceUrl = findUrlToUser(searchingCommentParent).href;
|
||||||
|
|
||||||
|
chrome.runtime.sendMessage({videoUrl: location.href}); // save video URL
|
||||||
|
chrome.runtime.sendMessage({toDeleteUserId: referenceUrl}); // save user URL
|
||||||
|
|
||||||
|
// get authentication token
|
||||||
|
window.open("https://accounts.google.com/o/oauth2/v2/auth?client_id="+google_login_client_id+"&redirect_uri=https://youtube.com/deleteallcomments&response_type=token&scope=https://www.googleapis.com/auth/youtube.force-ssl")
|
||||||
|
}
|
||||||
|
|
||||||
|
function findMainParentOfReplyCTA(pointerEvent) {
|
||||||
|
var searchingCommentParent = pointerEvent.currentTarget;
|
||||||
|
while(searchingCommentParent.id != "main") {
|
||||||
|
searchingCommentParent = searchingCommentParent.parentElement;
|
||||||
|
}
|
||||||
|
return searchingCommentParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
function findUrlToUser(mainElement) {
|
||||||
|
for (var i = 0; i < mainElement.childElementCount; i++) {
|
||||||
|
if (mainElement.id == "author-text") {
|
||||||
|
return mainElement;
|
||||||
|
} else {
|
||||||
|
var childResult = findUrlToUser(mainElement.children[i]);
|
||||||
|
if (childResult != null) {
|
||||||
|
return childResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
observer.observe(document.body, {
|
||||||
|
childList: true,
|
||||||
|
subtree: true,
|
||||||
|
attributes: false,
|
||||||
|
characterData: false
|
||||||
|
});
|
||||||
1
deleteallcomment.js
Normal file
1
deleteallcomment.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
chrome.runtime.sendMessage({tokenWithUrl: location.href}); // just give the data to the background js
|
||||||
156
deleting.css
Normal file
156
deleting.css
Normal file
|
|
@ -0,0 +1,156 @@
|
||||||
|
/* infinite loading indicator */
|
||||||
|
.loader {
|
||||||
|
margin-top: 30px;
|
||||||
|
border: 4px solid #CCCCCC;
|
||||||
|
border-radius: 100%;
|
||||||
|
border-top: 4px solid #7d3a94;
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
animation: spin 1s infinite cubic-bezier(.1, .4, .7, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
0% { transform: rotate(0deg); }
|
||||||
|
100% { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* progress bar with percentage value */
|
||||||
|
/* expected HTML
|
||||||
|
<div class="progress-bar" id="progress-bar">
|
||||||
|
<div class="progressbar-background"></div>
|
||||||
|
<div class="progress-number" id="progress-number">100%</div>
|
||||||
|
<div class="progressbar-progress" id="progress-moving"></div>
|
||||||
|
<div class="progressbar-progress-cut" id="progress-cut"></div>
|
||||||
|
<div class="progressbar-progress" id="progress-second-half"></div>
|
||||||
|
</div>
|
||||||
|
*/
|
||||||
|
.progress-bar {
|
||||||
|
visibility: hidden;
|
||||||
|
margin-top: 30px;
|
||||||
|
width: 56px;
|
||||||
|
height: 56px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progressbar-background {
|
||||||
|
position: absolute;
|
||||||
|
border: 4px solid #CCCCCC;
|
||||||
|
border-radius: 100%;
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progressbar-progress {
|
||||||
|
position: absolute;
|
||||||
|
border: 4px solid transparent;
|
||||||
|
border-top: 4px solid #7d3a94;
|
||||||
|
border-right: 4px solid #7d3a94;
|
||||||
|
border-radius: 100%;
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.progressbar-progress-cut {
|
||||||
|
position: absolute;
|
||||||
|
border: 4px solid transparent;
|
||||||
|
border-top: 4px solid #CCCCCC;
|
||||||
|
border-right: 4px solid #CCCCCC;
|
||||||
|
border-radius: 100%;
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-number {
|
||||||
|
position: absolute;
|
||||||
|
font: 16px arial, serif;
|
||||||
|
margin: auto;
|
||||||
|
text-align: center;
|
||||||
|
display:flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 56px;
|
||||||
|
width: 56px;
|
||||||
|
color: #CCCCCC
|
||||||
|
}
|
||||||
|
|
||||||
|
/* general texts */
|
||||||
|
span {
|
||||||
|
font: 20px arial, serif;
|
||||||
|
color: #CCCCCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font: 20px arial, serif;
|
||||||
|
color: #CCCCCC
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
font: 20px arial, serif;
|
||||||
|
color: #DDDDDD
|
||||||
|
}
|
||||||
|
|
||||||
|
/* additional space for the progress process elements */
|
||||||
|
.progress {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sample button */
|
||||||
|
.infoButton {
|
||||||
|
background-color: transparent;
|
||||||
|
border: 2px solid #7d3a94;
|
||||||
|
color: #CCCCCC;
|
||||||
|
padding: 15px 32px;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 16px;
|
||||||
|
margin: 4px 2px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition-duration: 0.4s;
|
||||||
|
border-radius: 16px;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
.infoButton:hover {
|
||||||
|
background-color: #7d3a94;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* delete button */
|
||||||
|
.actionButton {
|
||||||
|
background-color: transparent;
|
||||||
|
border: 2px solid #6d2a84;
|
||||||
|
color: #CCCCCC;
|
||||||
|
padding: 15px 32px;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 16px;
|
||||||
|
margin: 4px 2px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition-duration: 0.4s;
|
||||||
|
border-radius: 16px;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
.actionButton:hover {
|
||||||
|
background-color: #6d2a84;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Comments samle */
|
||||||
|
.comment {
|
||||||
|
margin-top: 6px;
|
||||||
|
border: 3px solid #7d3a94;
|
||||||
|
padding: 8px;
|
||||||
|
padding-left: 16px;
|
||||||
|
padding-right: 16px;
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment-text {
|
||||||
|
text-align: start;
|
||||||
|
font: 16px arial, serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment-name {
|
||||||
|
text-align: start;
|
||||||
|
font: 12px arial, serif;
|
||||||
|
}
|
||||||
43
deleting.html
Normal file
43
deleting.html
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Deleting comments!</title>
|
||||||
|
<script type="text/javascript" src="deleting.js"></script>
|
||||||
|
<link rel="stylesheet" href="deleting.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body body style="background-color:#35363A;">
|
||||||
|
<div align="center">
|
||||||
|
<div style="max-width: 35%; margin-top: 48px;">
|
||||||
|
<span id="search_description"></span>
|
||||||
|
<div class="loader" id="first-request-loading"></div>
|
||||||
|
<div class="progress"> <!-- progress bar while loading threads and filtering comments -->
|
||||||
|
<p id="number_of_comment_threads"></p>
|
||||||
|
<div class="progress-bar" id="progress-bar-comments">
|
||||||
|
<div class="progressbar-background"></div>
|
||||||
|
<div class="progress-number" id="progress-number-comments">100%</div>
|
||||||
|
<div class="progressbar-progress" id="progress-moving-comments"></div>
|
||||||
|
<div class="progressbar-progress-cut" id="progress-cut-comments"></div>
|
||||||
|
<div class="progressbar-progress" id="progress-second-half-comments"></div>
|
||||||
|
</div>
|
||||||
|
<p id="comments_to_be_deleted"></p>
|
||||||
|
|
||||||
|
<button id="show_sample_cta" class="infoButton">Show Sample</button>
|
||||||
|
<button id="delete_all_cta" class="actionButton">Delete All</button>
|
||||||
|
<div id="comment_sample_placeholder"></div> <!-- sample comments will be added here -->
|
||||||
|
|
||||||
|
<div class="progress-bar" id="progress-bar-delete"> <!-- progress bar while deleting the comments -->
|
||||||
|
<div class="progressbar-background"></div>
|
||||||
|
<div class="progress-number" id="progress-number-delete">100%</div>
|
||||||
|
<div class="progressbar-progress" id="progress-moving-delete"></div>
|
||||||
|
<div class="progressbar-progress-cut" id="progress-cut-delete"></div>
|
||||||
|
<div class="progressbar-progress" id="progress-second-half-delete"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p id="comments_deleted_so_far"></p>
|
||||||
|
<p id="couldnt_delete_comments_so_far"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
197
deleting.js
Normal file
197
deleting.js
Normal file
|
|
@ -0,0 +1,197 @@
|
||||||
|
// HTML DOOM ELEMENT IDS
|
||||||
|
var SEARCH_DESCRIPTION_ID = "search_description"
|
||||||
|
var FIRST_REQUEST_LOADER_ID = "first-request-loading"
|
||||||
|
var NUMBER_OF_COMMENT_THREADS_LOADED_ID = "number_of_comment_threads"
|
||||||
|
var NUMBER_OF_COMMENTS_TO_DELETE_ID = "comments_to_be_deleted"
|
||||||
|
var DELETE_COMMENTS_NUMBER_PROGRESS_ID = "comments_deleted_so_far"
|
||||||
|
var COULDNT_DELETE_COMMENTS_NUMBER_PROGRESS_ID = "couldnt_delete_comments_so_far"
|
||||||
|
var COMMENTS_TO_DELETE_PROGRESS_ID = "-comments"
|
||||||
|
var COMMENTS_DELETING_PROCESS_ID = "-delete"
|
||||||
|
var SHOW_SAMPLE_CTA_ID = "show_sample_cta"
|
||||||
|
var DELETE_ALL_CTA_ID = "delete_all_cta"
|
||||||
|
var COMMENT_SAMPLE_PLACEHOLDER_ID = "comment_sample_placeholder"
|
||||||
|
|
||||||
|
// global references
|
||||||
|
var youtubeToken = ""
|
||||||
|
var toDeleteUserId = ""
|
||||||
|
var videoId = ""
|
||||||
|
var commentResponses = []
|
||||||
|
var commentsToDelete = []
|
||||||
|
var isSampleShown = false
|
||||||
|
|
||||||
|
chrome.runtime.sendMessage({greeting: "hello"}, function(response) {
|
||||||
|
document.getElementById(SEARCH_DESCRIPTION_ID).innerHTML = "Searching through the comments of the following video: <a href=\"https://www.youtube.com/watch?v=" + response.videoUrl + "\">video link (" + response.videoUrl + ")</a> by the following user: <a href=\"https://www.youtube.com/channel/" + response.toDeleteUserId + "\">user profile (" + response.toDeleteUserId + ")</a>"
|
||||||
|
youtubeToken = response.youtubetoken;
|
||||||
|
toDeleteUserId = response.toDeleteUserId;
|
||||||
|
videoId = response.videoId;
|
||||||
|
|
||||||
|
runFindCommentThreadsRequest("", 0)
|
||||||
|
});
|
||||||
|
|
||||||
|
function runFindCommentThreadsRequest(pageToken, numberOfCommentsFoundSoFar) {
|
||||||
|
const request = new XMLHttpRequest();
|
||||||
|
const url = 'https://www.googleapis.com/youtube/v3/commentThreads?part=id,replies,snippet&videoId=' + videoId + "&access_token=" + youtubeToken + "&pageToken=" + pageToken;
|
||||||
|
request.open("GET", url);
|
||||||
|
|
||||||
|
request.onreadystatechange = (e) => {
|
||||||
|
if (request.readyState === XMLHttpRequest.DONE) {
|
||||||
|
var status = request.status;
|
||||||
|
if (status >= 200 && status < 400) {
|
||||||
|
var responseJson = JSON.parse(request.responseText)
|
||||||
|
onCommentThreadsReceived(responseJson, numberOfCommentsFoundSoFar)
|
||||||
|
} else {
|
||||||
|
console.log("status = " + request.status + " response =" + request.responseText)
|
||||||
|
onCommentThreadsAccessError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
request.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onCommentThreadsAccessError() {
|
||||||
|
document.getElementById(FIRST_REQUEST_LOADER_ID).style.display = "none"
|
||||||
|
document.getElementById(NUMBER_OF_COMMENT_THREADS_LOADED_ID).innerHTML = "Something went wrong while accessing comment threads of the video, please try again"
|
||||||
|
}
|
||||||
|
|
||||||
|
function onCommentThreadsReceived(responseJson, numberOfCommentsFoundSoFar) {
|
||||||
|
commentResponses.push(responseJson)
|
||||||
|
var newTotalCommentsCount = numberOfCommentsFoundSoFar + responseJson.pageInfo.totalResults
|
||||||
|
document.getElementById(NUMBER_OF_COMMENT_THREADS_LOADED_ID).innerHTML = "Comment threads accessed: " + newTotalCommentsCount
|
||||||
|
if (responseJson.nextPageToken == null) {
|
||||||
|
onCommentThreadsFound(commentResponses, newTotalCommentsCount)
|
||||||
|
} else {
|
||||||
|
runFindCommentThreadsRequest(responseJson.nextPageToken, newTotalCommentsCount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onCommentThreadsFound(commentResponses, totalCountOfThreads) {
|
||||||
|
document.getElementById(NUMBER_OF_COMMENT_THREADS_LOADED_ID).innerHTML = "Number Of Comment Threads: " + totalCountOfThreads
|
||||||
|
document.getElementById(FIRST_REQUEST_LOADER_ID).style.display = "none"
|
||||||
|
var commentThreadProcessed = 0;
|
||||||
|
var foundCommentsToDelete = []
|
||||||
|
setProgressOfProgressBar(COMMENTS_TO_DELETE_PROGRESS_ID, 0)
|
||||||
|
|
||||||
|
for (var i = 0; i < commentResponses.length; i++) {
|
||||||
|
var comentThreadResponses = commentResponses[i]
|
||||||
|
for (var j = 0; j < comentThreadResponses.items.length; j++) {
|
||||||
|
var commentThread = comentThreadResponses.items[j]
|
||||||
|
foundCommentsToDelete = foundCommentsToDelete.concat(getMatchingCommentIdsFromCommentThread(commentThread))
|
||||||
|
commentThreadProcessed = commentThreadProcessed + 1;
|
||||||
|
setProgressOfProgressBar(COMMENTS_TO_DELETE_PROGRESS_ID, Math.floor(commentThreadProcessed * 100 / totalCountOfThreads))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
commentsToDelete = foundCommentsToDelete
|
||||||
|
document.getElementById(NUMBER_OF_COMMENTS_TO_DELETE_ID).innerHTML = "Number of comments to be deleted: " + foundCommentsToDelete.length
|
||||||
|
document.getElementById(SHOW_SAMPLE_CTA_ID).style.visibility = "visible"
|
||||||
|
document.getElementById(SHOW_SAMPLE_CTA_ID).addEventListener("click", showSample);
|
||||||
|
document.getElementById(DELETE_ALL_CTA_ID).style.visibility = "visible"
|
||||||
|
document.getElementById(DELETE_ALL_CTA_ID).addEventListener("click", deleteAllComments);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setProgressOfProgressBar(id, progress) {
|
||||||
|
document.getElementById("progress-bar" + id).style.visibility = 'visible'
|
||||||
|
if (progress < 50) {
|
||||||
|
var progressInDegrees = Math.floor(progress * 3.6) + 45;
|
||||||
|
document.getElementById("progress-second-half" + id).style.visibility = 'hidden'
|
||||||
|
document.getElementById("progress-moving" + id).style.transform = "rotate(45deg)";
|
||||||
|
document.getElementById("progress-cut" + id).style.transform = "rotate(" + progressInDegrees + "deg)";
|
||||||
|
} else {
|
||||||
|
var progressInDegrees = Math.floor((progress - 50) * 3.6) + 225;
|
||||||
|
document.getElementById("progress-second-half" + id).style.visibility = 'visible'
|
||||||
|
document.getElementById("progress-moving" + id).style.transform = "rotate(225deg)";
|
||||||
|
document.getElementById("progress-cut" + id).style.transform = "rotate(" + progressInDegrees + "deg)";
|
||||||
|
}
|
||||||
|
document.getElementById("progress-number" + id).innerHTML = progress + "%"
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMatchingCommentIdsFromCommentThread(commentThreadObject) {
|
||||||
|
var foundComments = []
|
||||||
|
var topLevelComment = commentThreadObject.snippet.topLevelComment
|
||||||
|
if (isCommentMathingAuthor(topLevelComment)) {
|
||||||
|
foundComments.push(topLevelComment)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commentThreadObject.replies != null && commentThreadObject.replies.comments != null) {
|
||||||
|
for (i = 0; i < commentThreadObject.replies.comments.length; i++) {
|
||||||
|
var comment = commentThreadObject.replies.comments[i]
|
||||||
|
if (isCommentMathingAuthor(comment)) {
|
||||||
|
foundComments.push(comment)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return foundComments;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isCommentMathingAuthor(comment) {
|
||||||
|
return comment.snippet.authorChannelId.value === toDeleteUserId
|
||||||
|
}
|
||||||
|
|
||||||
|
function showSample() {
|
||||||
|
if (isSampleShown) return
|
||||||
|
isSampleShown = true
|
||||||
|
|
||||||
|
for (i = 0; i < commentsToDelete.length && i < 3; i++) {
|
||||||
|
var commentToShow = commentsToDelete[i];
|
||||||
|
var divTag = document.createElement("div");
|
||||||
|
divTag.setAttribute("class", "comment")
|
||||||
|
|
||||||
|
var userNameTag = document.createElement("p");
|
||||||
|
divTag.appendChild(userNameTag);
|
||||||
|
userNameTag.setAttribute("class", "comment-name")
|
||||||
|
userNameTag.innerHTML = "name: " + commentToShow.snippet.authorDisplayName
|
||||||
|
|
||||||
|
var commentTag = document.createElement("p");
|
||||||
|
divTag.appendChild(commentTag);
|
||||||
|
commentTag.setAttribute("class", "comment-text")
|
||||||
|
commentTag.innerHTML = "comment: " + commentToShow.snippet.textDisplay
|
||||||
|
|
||||||
|
document.getElementById(COMMENT_SAMPLE_PLACEHOLDER_ID).appendChild(divTag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteAllComments() {
|
||||||
|
setProgressOfProgressBar(COMMENTS_DELETING_PROCESS_ID, 0)
|
||||||
|
deleteComment(0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteComment(index, failures) {
|
||||||
|
if (commentsToDelete.length <= index) {
|
||||||
|
onAllCommentsDeleted(failures);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const request = new XMLHttpRequest();
|
||||||
|
const url = 'https://www.googleapis.com/youtube/v3/comments?id=' + commentsToDelete[index].id + "&access_token=" + youtubeToken;
|
||||||
|
request.open("DELETE", url);
|
||||||
|
|
||||||
|
request.onreadystatechange = (e) => {
|
||||||
|
if (request.readyState === XMLHttpRequest.DONE) {
|
||||||
|
|
||||||
|
setProgressOfProgressBar(COMMENTS_DELETING_PROCESS_ID, Math.floor((index + 1) / commentsToDelete.length * 100))
|
||||||
|
var status = request.status;
|
||||||
|
var failuresAdjusted = failures
|
||||||
|
if (status >= 200 && status < 400) {
|
||||||
|
document.getElementById(DELETE_COMMENTS_NUMBER_PROGRESS_ID).innerHTML = "Number of comments deleted so far: " + (index + 1)
|
||||||
|
} else {
|
||||||
|
failuresAdjusted = failures + 1
|
||||||
|
document.getElementById(COULDNT_DELETE_COMMENTS_NUMBER_PROGRESS_ID).innerHTML = "Number of comments couldn't delete so far: " + failuresAdjusted
|
||||||
|
}
|
||||||
|
deleteComment(index + 1, failuresAdjusted)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
request.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onAllCommentsDeleted(failures) {
|
||||||
|
if (failures == 0) {
|
||||||
|
document.getElementById(DELETE_COMMENTS_NUMBER_PROGRESS_ID).innerHTML = "All comments are deleted(" + commentsToDelete.length + "), closing tab in 3 seconds..."
|
||||||
|
setTimeout(function() {
|
||||||
|
chrome.runtime.sendMessage({
|
||||||
|
closeMe: "true"
|
||||||
|
});
|
||||||
|
}, 3000);
|
||||||
|
} else {
|
||||||
|
var successCount = commentsToDelete.length - failures
|
||||||
|
document.getElementById(DELETE_COMMENTS_NUMBER_PROGRESS_ID).innerHTML = "Couldn't delete all the comments, but did delete: " + successCount
|
||||||
|
}
|
||||||
|
}
|
||||||
11
hello.html
Normal file
11
hello.html
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Youtube Spam Purger!</title>
|
||||||
|
</head>
|
||||||
|
<body style="min-width: 200px;">
|
||||||
|
<p>Next to comments on videos will show a DELETE All COMMENTS button.</p>
|
||||||
|
<p>Clicking that will navigate you to a new page where you may delete that user's comments from that video.</p>
|
||||||
|
<p>You may need to login to Google for it to work after clicking the button</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
23
manifest.json
Normal file
23
manifest.json
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"name": "Youtube Spam Purge!",
|
||||||
|
"version": "1.0",
|
||||||
|
"manifest_version": 3,
|
||||||
|
"background": {
|
||||||
|
"service_worker": "background.js"
|
||||||
|
},
|
||||||
|
"action": {
|
||||||
|
"default_popup": "hello.html"
|
||||||
|
},
|
||||||
|
"permissions": [
|
||||||
|
"tabs"
|
||||||
|
],
|
||||||
|
"content_scripts": [{
|
||||||
|
"css": ["content-styles.css"],
|
||||||
|
"js": ["content.js","clientid.js"],
|
||||||
|
"matches": ["https://www.youtube.com/watch?v=*"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"js": ["deleteallcomment.js"],
|
||||||
|
"matches": ["https://www.youtube.com/deleteallcomments"]
|
||||||
|
}]
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue