-
Notifications
You must be signed in to change notification settings - Fork 0
/
Youtube Comment Cleaner (YCC).user.js
189 lines (163 loc) · 7.33 KB
/
Youtube Comment Cleaner (YCC).user.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
// ==UserScript==
// @name Youtube Comment Cleaner (YCC)
// @description Allows batch-deletion of Youtube comments, live chat messages and comment likes/dislikes
// @author Fonic <https://github.com/fonic>
// @author Christian Prior-Mamulyan <https://github.com/cprima> (orginal script)
// @homepage https://github.com/fonic/Youtube-Comment-Cleaner
// @supportURL https://github.com/fonic/Youtube-Comment-Cleaner
// @downloadURL https://github.com/fonic/Youtube-Comment-Cleaner/raw/main/Youtube%20Comment%20Cleaner%20%28YCC%29.user.js
// @updateURL https://github.com/fonic/Youtube-Comment-Cleaner/raw/main/Youtube%20Comment%20Cleaner%20%28YCC%29.user.js
// @namespace myactivity.google.com
// @match https://myactivity.google.com/page?hl=en&page=youtube_comments
// @match https://myactivity.google.com/page?hl=en&utm_medium=web&utm_source=youtube&page=youtube_comments
// @match https://myactivity.google.com/page?hl=en&page=youtube_live_chat
// @match https://myactivity.google.com/page?hl=en&utm_medium=web&utm_source=youtube&page=youtube_live_chat
// @match https://myactivity.google.com/page?hl=en&page=youtube_comment_likes
// @match https://myactivity.google.com/page?hl=en&utm_medium=web&utm_source=youtube&page=youtube_comment_likes
// @version 1.0
// @grant none
// @run-at context-menu
// ==/UserScript==
/**
* Based on: https://gist.github.com/cprima/2f7ea8e353c18a666506021c85e9773d
* Original author's notes:
*
* Google MyActivity YouTube Comment Deletion Script
*
* Script to assist in bulk deletion of YouTube comments from Google's MyActivity.
*
* Usage:
* - Navigate to MyActivity YouTube Comments page.
* - Open browser's developer console.
* - Copy-paste this script, and follow on-screen prompts.
*
* Features:
* - Deletes comments from bottom (oldest first).
* - User control: specify number to delete, or cancel anytime.
*
* Safety:
* - Halting: 'cancel' during prompt or close tab.
*
* Author: Christian Prior-Mamulyan
* License: MIT
* Source: https://gist.github.com/cprima/2f7ea8e353c18a666506021c85e9773d
*
* Use cautiously. Deletion is irreversible.
*/
function ensureOnCorrectActivityPage() {
const elementsData = [
{
url: "https://myactivity.google.com/page?hl=en&page=youtube_comments",
content: "Your YouTube Comments"
},
{
url: "https://myactivity.google.com/page?hl=en&utm_medium=web&utm_source=youtube&page=youtube_comments",
content: "Your YouTube Comments"
},
{
url: "https://myactivity.google.com/page?hl=en&page=youtube_live_chat",
content: "Your YouTube Live Chat Messages"
},
{
url: "https://myactivity.google.com/page?hl=en&utm_medium=web&utm_source=youtube&page=youtube_live_chat",
content: "Your YouTube Live Chat Messages"
},
{
url: "https://myactivity.google.com/page?hl=en&page=youtube_comment_likes",
content: "Your Likes and Dislikes on YouTube Comments"
},
{
url: "https://myactivity.google.com/page?hl=en&utm_medium=web&utm_source=youtube&page=youtube_comment_likes",
content: "Your Likes and Dislikes on YouTube Comments"
}
];
const currentUrl = window.location.href;
const elementsWithClass = Array.from(document.querySelectorAll('.jPCT6'));
for (let elementData of elementsData) {
if (currentUrl.startsWith(elementData.url)) {
if (elementsWithClass.some(el => el.textContent.toLowerCase().includes(elementData.content.toLowerCase()))) {
console.log(`Matched URL: ${elementData.url} with content: "${elementData.content}"`);
return true; // Matched desired URL with corresponding content.
}
}
}
console.log(`You are not on a recognized page. Please navigate to 'Your YouTube Comments', 'Your YouTube Live Chat Messages' or 'Your Likes and Dislikes on YouTube Comments'.`);
return false;
}
async function scrollToBottom() {
while (!document.evaluate('//div[contains(text(), "Looks like you\'ve reached the end")]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue) {
window.scrollTo(0, document.body.scrollHeight);
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
function highlightElement(el) {
el.style.backgroundColor = '#ffcccb'; // Light red
setTimeout(() => {
el.style.backgroundColor = ''; // Reset background color after 1s
}, 1000);
}
function determineBestSelector() {
const SELECTORS = [
'.VfPpkd-Bz112c-LgbsSe.yHy1rc.eT1oJ.mN1ivc',
'[aria-label^="Delete activity item"]',
'[jscontroller="soHxf"]'
];
// Get the selector that matches the least amount of elements (more specific)
SELECTORS.sort((a, b) => document.querySelectorAll(a).length - document.querySelectorAll(b).length);
return SELECTORS[0];
}
async function deleteItems(deleteBatchSize) {
let deleteButtons = [];
const bestSelector = determineBestSelector();
if (!deleteButtons.length) {
deleteButtons = [...document.querySelectorAll(bestSelector)]; //.reverse();
}
let count = 0;
while (deleteButtons.length && (count < deleteBatchSize || deleteBatchSize === Infinity)) {
const btn = deleteButtons.pop();
// Scroll to the button to make it visible before deletion
btn.scrollIntoView({
behavior: 'smooth',
block: 'center'
});
await new Promise(resolve => setTimeout(resolve, 1000)); // Give a moment for the scroll to finish
highlightElement(btn);
await new Promise(resolve => setTimeout(resolve, 2000)); // Wait for 2s for the highlight to be visible
btn.click();
count++;
await new Promise(resolve => setTimeout(resolve, 1500));
}
return deleteButtons.length; // Return the number of remaining items
}
async function initiateItemDeletion() {
if (!ensureOnCorrectActivityPage()) {
return;
}
await scrollToBottom();
const bestSelector = determineBestSelector();
const totalItems = document.querySelectorAll(bestSelector).length;
if (!totalItems) {
console.log("No items found for deletion.");
return;
}
let userInput = prompt(`Found ${totalItems} items. Enter 'a' to delete all items or input a number to delete that many items. Press 'Cancel' at any time to stop the script:`);
while (userInput !== null) {
if (userInput.toLowerCase() === 'a') {
await deleteItems(Infinity);
console.log("All items deleted.");
return;
} else if (!isNaN(parseInt(userInput))) {
const deleteBatchSize = parseInt(userInput);
const remainingItems = await deleteItems(deleteBatchSize);
if (!remainingItems) {
console.log("All items deleted.");
return;
}
userInput = prompt(`${remainingItems} items remaining. Enter 'a' to delete all remaining items or input a number to delete that many items. Press 'Cancel' at any time to stop the script:`);
} else {
userInput = prompt("Invalid input. Please enter 'a' or a number:");
}
}
console.log("Operation canceled. No further items will be deleted.");
}
initiateItemDeletion();