Reddit: Post, clear, and delete

21/05/2013

Reddit: Post, clear, and delete

For a year or so, I’ve been using a very useful and effective GreaseMonkey script, which deletes all of my Reddit posts.
Userscripts: Delete All Comments – it also deletes posts.

Reddit Enhancement Suite
Together with the Reddit Enhancement Suite option of auto scroll, clearing my history is achieved in a single click.

All good, but I came across a post on Reddit, by one of the mods, stating that deleted posts could still be read. That the last posted edit was cached away for reference by whomever was empowered to view them.

Not really an issue, but the aim of deleting posts is to erm delete them, so I have taken it on as a mission to either find a script that will edit over a post, then delete it, or build one of my own.

Now I’ve never built a GreaseMonkey script before, and I am not fully fluent in javascript, although I do understand it, and with a little trial and error I hope to be able to fudge my way through it.

Also there are a heap of sites available where I can request help, and this will be a great chance to get au fe with them… StackExchange, I am thinking of you.

Insert: Turns out I didn’t need to put my coding skills to the test, my google-fu came through 🙂
Here’s the new delete script: Reddit Secure Delete


So here’s the original code I’m using for starters, thanks to AVRPunk, let us play 🙂

// ==UserScript==
// @name delete all reddit comments
// @namespace http://blah
// @include http://www.reddit.com/user/*
// ==/UserScript==

location.href = “javascript:(” + function()
{

var deleted = 0;
var links = document.getElementsByTagName(“a”);
var i = 0;
var d = 0;

for (i = 0; i < links.length; i++)
{

var l = links[i];
if (l.href)
{
if (l.innerHTML == “delete”)
{
toggle(l);
d = 1;
}
if (d && (l.innerHTML == “yes”))
{
deleted++;

l.id=’xxx’+i;

var butter=”document.getElementById(‘xxx”+i+”‘)”;

var f=function(a)
{
hide_thing(a);
};

setTimeout(“change_state( “+butter+”, ‘del’, hide_thing)”, 1000*deleted);

d=0;
}
}

}

if(deleted>0)
{
setTimeout(“location.reload(true);”,1000*(deleted+1));
}

} + “)()”;

This solution is more than I could have dreamed of putting together with my limited skills, learn I will
// ==UserScript==
// @name Reddit Secure Delete
// @namespace Reddit
// @include https://*.reddit.com/*
// @include http://*.reddit.com/*
// @version 1
// ==/UserScript==

unsafeWindow.to_delete = [];
unsafeWindow.num_user_comments = 0;
unsafeWindow.deleted = 0;
unsafeWindow.span = ”;
unsafeWindow.user = ”;

unsafeWindow.delete_comment = function(thing_id, from_delete_all)
{
try{
var thing = document.querySelector(“input[name=’thing_id’][value='” + thing_id + “‘]”);

var status = thing.parentNode.querySelector(“div.usertext-edit > div.bottom-area > div.usertext-buttons > span.status”).innerHTML;

var error = false;
if ((status.indexOf(“error”) != -1) || (status.indexOf(“submitting”) != -1)){
error = true;
} else {
var del_form = thing.parentNode.parentNode.querySelector(“ul.buttons > li > form.del-button”);
unsafeWindow.toggle(del_form.querySelector(“span.main > a”));
del_form.querySelector(“span.error > a.yes”).click();
unsafeWindow.deleted++;
}

if (from_delete_all){
if (unsafeWindow.to_delete.length != 0)
{
unsafeWindow.span.innerHTML = “TRYING TO DELETE COMMENT ” + (unsafeWindow.deleted + 1) + ” OF ” + unsafeWindow.num_user_comments;
var next_thing_id = unsafeWindow.to_delete.pop();
unsafeWindow.setTimeout(unsafeWindow.overwrite_comment, 2000, next_thing_id, from_delete_all);
}
else
{
if (unsafeWindow.num_user_comments – unsafeWindow.deleted != 0){
unsafeWindow.num_user_comments = unsafeWindow.num_user_comments – unsafeWindow.deleted;
UpdateDeleteAllSpan();
unsafeWindow.span.innerHTML = “Failed to delete ” + unsafeWindow.num_user_comments + ” comments
” + unsafeWindow.span.innerHTML;
} else
unsafeWindow.span.style.display = ‘none’;

}
} else {
if (error)
alert(“Failed to overwrite your comment. Delete aborted.”);
else
unsafeWindow.num_user_comments–;
UpdateDeleteAllSpan();
}
return (error ? -1 : 0);
}catch(er){
alert(er);
if (from_delete_all) unsafeWindow.location.reload();
return -99;
}
}

unsafeWindow.overwrite_comment = function(thing_id, from_delete_all)
{
try{
var edit_form = document.querySelector(“input[name=’thing_id’][value='” + thing_id + “‘]”).parentNode;

edit_form.querySelector(“div.usertext-edit > div.bottom-area > div.usertext-buttons > button.cancel”).click();

var edit_btn = edit_form.parentNode.querySelector(“ul > li > a.edit-usertext”);
if (edit_btn) edit_btn.click();
var edit_textbox = edit_form.querySelector(“div.usertext-edit > div > textarea”);
var repl_str = ”;
var chars = “0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz><.-,+!@#$%^&*();:[]~”;
for(var x = 0; x < edit_textbox.value.length; x++){
if (edit_textbox.value.substr(x,1) == ‘\n’){
repl_str += ‘\n’;
}else{
var rnum = Math.floor(Math.random() * chars.length);
repl_str += chars.charAt(rnum, 1);
}
}
edit_textbox.value = repl_str;
edit_form.querySelector(“div.usertext-edit > div.bottom-area > div.usertext-buttons > button.save”).click();
unsafeWindow.setTimeout(unsafeWindow.delete_comment, 2000, thing_id, from_delete_all);
return 0;
}catch(e){
alert(“Error interacting with overwrite form: ” + e);
return -99;
}
};

unsafeWindow.delete_all = function()
{
try{
unsafeWindow.num_user_comments = 0;
unsafeWindow.deleted = 0;
unsafeWindow.to_delete = [];
var comments = document.querySelectorAll(“a.author”);
for (var i = 0; i < comments.length; i++)
{
if (comments[i].innerHTML != unsafeWindow.user) continue;
var thing_id = comments[i].parentNode.parentNode.querySelector(“form.usertext > input[name=’thing_id’]”).value;
if (unsafeWindow.to_delete.indexOf(thing_id) == -1){
unsafeWindow.to_delete.push(thing_id);
unsafeWindow.num_user_comments++;
}
}
unsafeWindow.span.innerHTML = “TRYING TO DELETE COMMENT 1 OF ” + unsafeWindow.num_user_comments;
var next_thing_id = unsafeWindow.to_delete.pop();
unsafeWindow.overwrite_comment(next_thing_id, true);
} catch(e){
alert(“Error trying to delete all your comments.\nError: ” + e);
unsafeWindow.location.reload()
}
};

function add_delete_links(ev)
{
unsafeWindow.user = document.querySelector(“span.user > a:not(.login-required)”).innerHTML;
if (!unsafeWindow.user){return;}
var comments = document.querySelectorAll(“a.author”);
unsafeWindow.num_user_comments = 0;
for (var i = 0; i < comments.length; i++)
{
if (comments[i].innerHTML != unsafeWindow.user) continue;
try{
var main_parent = comments[i].parentNode.parentNode;
var thing_id = main_parent.querySelector(“form > input[name=’thing_id’]”).value;
var list = main_parent.querySelector(“ul.flat-list”);
if (list.querySelector(“li.secure_delete”)) continue;
unsafeWindow.num_user_comments++;

var addedlink = document.createElement(“li”);
addedlink.setAttribute(‘class’, ‘secure_delete’);
var dlink = document.createElement(“a”);
dlink.setAttribute(‘class’,’bylink secure_delete’);
dlink.setAttribute(‘onClick’,’javascript:var ret = overwrite_comment(“‘ + thing_id + ‘”, false);’);
dlink.setAttribute(‘href’, ‘javascript:void(0)’);
dlink.appendChild(document.createTextNode(‘SECURE DELETE’));
addedlink.appendChild(dlink);
main_parent.querySelector(“ul.flat-list”).appendChild(addedlink);
}catch(e){}
}

unsafeWindow.span = document.createElement(“span”);
unsafeWindow.span.setAttribute(‘class’, ‘nextprev secure_delete_all’);
UpdateDeleteAllSpan();

}

function UpdateDeleteAllSpan()
{
if (unsafeWindow.num_user_comments){
unsafeWindow.span.innerHTML = “”;
var dlink = document.createElement(“a”);
dlink.setAttribute(‘class’,’bylink’);
dlink.setAttribute(‘onClick’,’javascript:return delete_all()’);
dlink.setAttribute(‘href’, ‘javascript:void(0)’);
dlink.appendChild(document.createTextNode(‘SECURE DELETE ‘ + unsafeWindow.num_user_comments + ‘ visible comment(s) on this page.’));
unsafeWindow.span.appendChild(dlink);
document.querySelector(“div.content”).insertBefore(unsafeWindow.span,document.querySelector(“div.content”).firstChild);
} else if (unsafeWindow.span != null) {
unsafeWindow.span.style.display = ‘none’;
}
}

window.addEventListener(“DOMContentLoaded”,add_delete_links, false);

Update!

Here’s a Tampermonkey script I’ve found for Chrome that does the same as above: Spaz’s Reddit Delete

// ==UserScript==
// @name Spaz's Reddit Delete
// @namespace Reddit
// @include http*://*.reddit.com/user/*
// @version 1
// @description Replaces all VISIBLE comments with garbage text, then deletes the comment. Works with RES!
// ==/UserScript==

RD = unsafeWindow.RedditDelete = {};
RD.DELAY_SAVE = 2 * 1000;
RD.DELAY_DELETE = 3 * 1000;
RD.chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz>< .-,+!@#$%^&*();:[]~'; RD.started = false;function __getRNGString(maxLength) { var rnum, repl_str = '';for (var x = 0; x < maxLength; x++){ rnum = Math.floor(Math.random() * RD.chars.length); repl_str += RD.chars.charAt(rnum, 1); }return repl_str; }function _setupEnv() { if (RD.started) return;RD.numDel = 0; RD.contentCtnr = document.querySelector('div.content'); RD.infoBar = document.createElement('span'); RD.userName = document.querySelector('span.user > a:not(.login-required)').innerHTML;
RD.infoBar.setAttribute('class', 'nextprev');
RD.started = true;
}

function _setupUI() {
//Build DELETE-ALL Link
var delAllLink = document.createElement('a');
delAllLink.innerHTML = 'Scorched Earth Engage';
delAllLink.onclick = _promptDeleteAll;
delAllLink.style.cssText = "color: rgb(200, 0, 0); text-shadow: -1px 0px 6px rgba(0,0,0, 0.7);";

//Add to infoBar!
RD.infoBar.appendChild(delAllLink);
RD.contentCtnr.insertBefore(RD.infoBar, RD.contentCtnr.firstChild);
}

function _promptDeleteAll() {
var doDelete = confirm("Are you sure you want to delete all comments on the screen?\n\n"
+ "ProTip: If you want to delete ALL, use RES and use 'Never Ending Reddit' feature to show ALL comments.");

if (!doDelete) return;

_deleteAll();
}

function _deleteAll() {
var modalCntr = RD.modalCntr = document.createElement('div');
var modalMsg = RD.modalMsg = document.createElement('div');
var cancelBtn = document.createElement('button');
modalCntr.style.cssText = ''
+ 'position: fixed; top: 0; left: 0; right: 0; bottom: 0;'
+ 'height: 100%; width: 100%; background: rgba(0,0,0,0.8);'

modalMsg.style.cssText = ''
+ 'position: absolute; font-size: 32px; transform: translateX(-50%); top: 50%; left: 50%;'

cancelBtn.style.cssText = ''
+ 'position: absolute; font-size: 22px;'
+ 'transform: translateX(-50%); top: 63%; left: 50%;'

cancelBtn.innerHTML = "Cancel";
cancelBtn.onclick = function() {
RD.modalMsg.innerHTML = "Cancelling..."
RD.numDel = RD.comments.length;
}

RD.comments = __getVisibleComments();
RD.numDel = 0;

modalCntr.appendChild(modalMsg);
modalCntr.appendChild(cancelBtn);
document.body.appendChild(modalCntr);

__deleteCommentIndex(0);
}

function __getVisibleComments() {
var foundComments = [];

var entries = RD.contentCtnr.querySelectorAll('.entry.likes');
var entry = null;
var entryAuthor = '';

for (var idx = 0; idx < entries.length; idx++) { entry = entries[idx]; entryAuthor = entry.querySelector('.author');if (!entryAuthor || entryAuthor.innerHTML !== RD.userName) continue;foundComments.push(entry); };return foundComments; }function __deleteCommentIndex(idx) { var comment = RD.comments[idx];__overwriteComment(comment, function(comment) { __deleteComment(comment, function() { var complete = RD.numDel >= RD.comments.length;
if (false === complete) {
RD.numDel++;
__deleteCommentIndex(RD.numDel);
} else {
window.location.reload();
}
});
});
}

function __overwriteComment(comment, callback) {
var editLink = comment.querySelector('.edit-usertext');
var editText, newText, saveLink;

RD.modalMsg.innerHTML = 'Overwriting ' + (RD.numDel + 1) + ' of ' + RD.comments.length + '...';

if (!editLink) { if (callback) callback(comment); return; }

//Enable editing...
editLink.click();
editText = comment.querySelector('textarea');
saveBtn = comment.querySelector('.usertext-buttons .save');

//Replace Text with RNG string
newText = __getRNGString(editText.value.length);
editText.value = newText;

//Do the save...
saveBtn.click();
setTimeout(function() { if (callback) callback(comment); }, RD.DELAY_SAVE);
}

function __deleteComment(comment, callback) {
RD.modalMsg.innerHTML = 'Deleting ' + (RD.numDel + 1) + ' of ' + RD.comments.length + '...';

var deleteLink = comment.querySelector('form.del-button .togglebutton')
var yesLink;

//Enable deleting...
deleteLink.click();
yesLink = comment.querySelector('.option.error.active a.yes');

if (!yesLink) { if (callback) callback(); return; }

//Delay clicking YES so the user can see it
setTimeout(function() {
//Do the delete...
yesLink.click();
setTimeout(function() { if (callback) callback(); }, RD.DELAY_DELETE);
}, 250);
}

(function() {
_setupEnv();
_setupUI();
})();