Skip to content

Instantly share code, notes, and snippets.

@banksJeremy
Created November 13, 2011 09:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save banksJeremy/1361876 to your computer and use it in GitHub Desktop.
Save banksJeremy/1361876 to your computer and use it in GitHub Desktop.
Stack Exchange deleted post user script

Stack Exchange Deleted Question Viewer

Screenshot

About

Stack Exchange Deleted Question Viewer is a user script which allows any users with at least 500 reputation to see most deleted posts, if they have a link to them. It will display the post's title, content, vote counts and comments. If the post has been edited at least once, it will also display the author and editor.

You can try this out with a deleted question and answer of mine on meta.stackoverflow.com, then consider taking a look at the Popular Deleted Questions list on meta.

Caveats

You will only be able to see answers when you use their permalink, or you voted on them answer before they were deleted. This will fail for locked questions, but should work for all others.

This script relies on certain bugs and design features that are likely to be changed at some point. I'll accommodate these changes if it's possible, but it may not be.

License

Released under the MIT Open Source License.

Installation

Click here to install Stack Exchange Deleted Question Viewer.

Platforms

Contact

Stack Exchange Deleted Question Viewer was written me, Jeremy Banks. You can just leave feedback in the comments, but if you would like to email me my address is in my profile.

Code

Stack Exchange Deleted Question Viewer was written in CoffeeScript. The source file is available here.

Oh, and...

...if any Stack Exchange folks would prefer that this be deleted, I won't object.

#!/usr/bin/env coffee --compile --bare
`// ==UserScript==
// @name Stack Exchange Deleted Question Viewer (Developer Trunk)
// @version 1.1
// @description (Intended for developer use only.)
// @namespace http://jeremybanks.ca/
// @include http://stackoverflow.com/*
// @include http://*.stackoverflow.com/*
// @include http://superuser.com/*
// @include http://*.superuser.com/*
// @include http://serverfault.com/*
// @include http://*.serverfault.com/*
// @include http://stackexchange.com/*
// @include http://*.stackexchange.com/*
// ==/UserScript==
`
load = (url, success, failure) ->
# Loads a script specified by a URL into the document.
e = document.createElement "script"
e.setAttribute "src", url
if success? then e.addEventListener "load", success
if failure? then e.addEventListener "error", failure
document.body.appendChild e
return e
inject = (f) ->
# Injects a function into the document and evaluates it.
#
# It is injected as source code, so it loses its current
# scope and gains a new one under the global scope.
e = document.createElement "script"
e.textContent = "(#{f})();"
document.body.appendChild e
return e
url = "https://raw.github.com/gist/1361876/deleted.user.js"
load url, null, -> console.error "Unable to load deleted question viewer trunk!"
// ==UserScript==
// @name Stack Exchange Deleted Question Viewer (Developer Trunk)
// @version 1.1
// @description (Intended for developer use only.)
// @namespace http://jeremybanks.ca/
// @include http://stackoverflow.com/*
// @include http://*.stackoverflow.com/*
// @include http://superuser.com/*
// @include http://*.superuser.com/*
// @include http://serverfault.com/*
// @include http://*.serverfault.com/*
// @include http://stackexchange.com/*
// @include http://*.stackexchange.com/*
// ==/UserScript==
;
var inject, load, url;
load = function(url, success, failure) {
var e;
e = document.createElement("script");
e.setAttribute("src", url);
if (success != null) e.addEventListener("load", success);
if (failure != null) e.addEventListener("error", failure);
document.body.appendChild(e);
return e;
};
inject = function(f) {
var e;
e = document.createElement("script");
e.textContent = "(" + f + ")();";
document.body.appendChild(e);
return e;
};
url = "https://raw.github.com/gist/1361876/deleted.user.js";
load(url, null, function() {
return console.error("Unable to load deleted question viewer trunk!");
});
#!/usr/bin/env coffee --compile --bare
`// ==UserScript==
// @name Stack Exchange Deleted Question Viewer
// @version 1.3.65535.0
// @description Allows you to view some deleted questions on Stack Exchange.
// @namespace http://jeremybanks.ca/
// @include http://stackoverflow.com/questions/*
// @include http://*.stackoverflow.com/questions/*
// @include http://superuser.com/questions/*
// @include http://*.superuser.com/questions/*
// @include http://serverfault.com/questions/*
// @include http://*.serverfault.com/questions/*
// @include http://stackexchange.com/questions/*
// @include http://*.stackexchange.com/questions/*
// @include http://answers.onstartups.com/questions/*
// ==/UserScript==
`
inject = (f) ->
# runs a function in the document (without user script restrictions and privileges)
script = document.createElement 'script'
script.textContent = "(#{f})();"
document.body.appendChild script
inject ->
start = ->
return unless location.pathname.match(/^\/questions\/\d+[\/$]/) and
document.title.match(/^Page Not Found - /) and
document.querySelector(".revision-comment")
console.log 'Deleted question detected, attempting to retrieve...'
if $?
do continueWithjQuery
else
script = document.createElement 'script'
script.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js'
script.addEventListener 'load', continueWithjQuery
document.body.appendChild script
markdownLoaded = undefined
answerFrame = null
continueWithjQuery = ->
submitForm = (url, data, method = 'POST') ->
form = $('<form>')
.attr(method: method, action: url)
.css(display: 'none')
addData = (name, data) ->
if $.isArray data
addData("#{name}[]", value) for value in data
else if typeof value is 'object'
addData("#{name}[#{key}]", value) for own key, value of data
else
form.append $('<input>').attr
type: 'hidden'
name: String name
value: String data
undefined
addData '', data
form.appendTo('body').submit()
submitForm "/questions/#{location.pathname.match(/^\/questions\/(\d+)[\/$]/)[1]}/answer/submit",
'post-text': 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
'display-name': 'nobody'
'm-address': 'example@example.com'
'home-page': 'http://example.com/'
do start
// ==UserScript==
// @name Stack Exchange Deleted Question Viewer
// @version 1.3.65535.0
// @description Allows you to view some deleted questions on Stack Exchange.
// @namespace http://jeremybanks.ca/
// @include http://stackoverflow.com/questions/*
// @include http://*.stackoverflow.com/questions/*
// @include http://superuser.com/questions/*
// @include http://*.superuser.com/questions/*
// @include http://serverfault.com/questions/*
// @include http://*.serverfault.com/questions/*
// @include http://stackexchange.com/questions/*
// @include http://*.stackexchange.com/questions/*
// @include http://answers.onstartups.com/questions/*
// ==/UserScript==
;
var inject;
var __hasProp = Object.prototype.hasOwnProperty;
inject = function(f) {
var script;
script = document.createElement('script');
script.textContent = "(" + f + ")();";
return document.body.appendChild(script);
};
inject(function() {
var answerFrame, continueWithjQuery, markdownLoaded, start;
start = function() {
var script;
if (!(location.pathname.match(/^\/questions\/\d+[\/$]/) && document.title.match(/^Page Not Found - /) && document.querySelector(".revision-comment"))) {
return;
}
console.log('Deleted question detected, attempting to retrieve...');
if (typeof $ !== "undefined" && $ !== null) {
return continueWithjQuery();
} else {
script = document.createElement('script');
script.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js';
script.addEventListener('load', continueWithjQuery);
return document.body.appendChild(script);
}
};
markdownLoaded = void 0;
answerFrame = null;
continueWithjQuery = function() {
var submitForm;
submitForm = function(url, data, method) {
var addData, form;
if (method == null) method = 'POST';
form = $('<form>').attr({
method: method,
action: url
}).css({
display: 'none'
});
addData = function(name, data) {
var key, value, _i, _len;
if ($.isArray(data)) {
for (_i = 0, _len = data.length; _i < _len; _i++) {
value = data[_i];
addData("" + name + "[]", value);
}
} else if (typeof value === 'object') {
for (key in data) {
if (!__hasProp.call(data, key)) continue;
value = data[key];
addData("" + name + "[" + key + "]", value);
}
} else {
form.append($('<input>').attr({
type: 'hidden',
name: String(name),
value: String(data)
}));
}
return;
};
addData('', data);
return form.appendTo('body').submit();
};
return submitForm("/questions/" + (location.pathname.match(/^\/questions\/(\d+)[\/$]/)[1]) + "/answer/submit", {
'post-text': 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
'display-name': 'nobody',
'm-address': 'example@example.com',
'home-page': 'http://example.com/'
});
};
return start();
});
all:
coffee --compile --bare .

Initial post IDs are taken from the URL.

For each known post ID:

  • /posts/ID/edit
    • Contains title, body source and tags of post.
    • If the post has been edited, it also contains the names, comments and IDs for each revision.
  • /posts/ID/comments
    • Contains the HTML text of the comments.
    • May provide the userid/name of the asker, if he has commented. Use this to get more info from real API.
  • /posts/ID/vote-counts
    • Contains the up/down vote counts for the post.
  • /posts/ID/votes (only use with the question)
    • Contains all votes/stars the user has cast on this question.
      • This may provide new post IDs to be searched.

Unused:

  • OP identification in comments
  • Tags at all (should be below post, at least)
    • Get counts via http://meta.stackoverflow.com/tags/TAGNAME/subscriber-info but with a huge throttle, because it's unimportant.
  • Infer rough version of title from URL, before full title is known.
  • Display real vote score, until it's clicked on.
  • Add flagging flaggy button stuff.

Do something in the side bar: maybe display revisions of the post?

Example revision-specific URL: http://meta.stackoverflow.com/posts/73412/edit/edc0a9c8-1ad0-44bf-94b9-608dba80b95d

/questions/QID/stub/AID#AID

work for links to deleted posts, as well.

@aschepler
Copy link

This doesn't seem to be working. It looks like the /posts/ URLs for deleted questions now return short "The post has been deleted and you can't..." documents.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment