tumblr_cleanr 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README +7 -0
- data/bin/tumblr_cleanr.rb +180 -0
- data/lib/tumblr_cleanr.rb +178 -0
- metadata +48 -0
data/README
ADDED
@@ -0,0 +1,180 @@
|
|
1
|
+
#See TumblrCleanr class for full documentation
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
# Note: not using Tumblr API because it does not support delete
|
5
|
+
# http://ruby-tumblr.rubyforge.org/
|
6
|
+
require 'mechanize' # http://mechanize.rubyforge.org/mechanize
|
7
|
+
require 'net/http' # http://www.ruby-doc.org/stdlib/libdoc/net/http/rdoc/classes/Net/HTTP.html
|
8
|
+
require 'uri'
|
9
|
+
require 'logger'
|
10
|
+
|
11
|
+
#== TumblrCleanr - clean/reset your tumblr by deleting all posts
|
12
|
+
#Author:: engtech (http://InternetDuctTape.com, http://rubeh.tumblr.com)
|
13
|
+
#Copyright:: Copyright (c) 2008 engtech
|
14
|
+
#License:: Creative Commons Attribution-Noncommercial 2.5 License
|
15
|
+
#
|
16
|
+
#Tumblr is rapidly becoming my favorite hosted blogging platform (more so than Blogger/WordPress.com) because of all the things they do correct:
|
17
|
+
#
|
18
|
+
#- RSS feed importing
|
19
|
+
#- free domain name support
|
20
|
+
#- free CSS/theme support
|
21
|
+
#- Google Analytics support
|
22
|
+
#- keeping it simple
|
23
|
+
#
|
24
|
+
#However, there's one feature that's missing: <b>how do you delete your Tumblr?</b> At some point you might want to destroy all traces of your tumblr (privacy concerns, or you want to use it for something else) and there isn't an option to do that -- other than click the delete button on every individual post. I wanted to repurpose a tumblr I had been using for feed aggregation and it had over 18,000 posts. That's a lot of clicks.
|
25
|
+
#
|
26
|
+
#Enter the TumblrCleanr. Provide it with your tumblr domain name as well as your username and password and it will delete up to the latest 3000 posts at a time. You can keep running it until your entire tumblr is clean as a whistle.
|
27
|
+
#
|
28
|
+
#== Privacy Concerns
|
29
|
+
#
|
30
|
+
#TumblrCleanr does not store your login information anywhere and only uses it to communicate with tumblr.com. Every time you run the program you will have to re-enter your login details.
|
31
|
+
#
|
32
|
+
#== Why Not Create a New Tumblr?
|
33
|
+
#
|
34
|
+
#That's true, it's much easier to create a new tumblr account with a different email address than it is to "reset" your existing Tumblr. You can even just change the tumblr domain name if you want to "free up" your good domain for something else. I created this more for my own learning process, because I wanted to try WWW::Mechanize, rdoc, rake and rubyscript2exe for the first time and give myself some more experience coding in Ruby.
|
35
|
+
#
|
36
|
+
#== License
|
37
|
+
#
|
38
|
+
#This work is licensed under the Creative Commons
|
39
|
+
#Attribution-Noncommercial 2.5 License.
|
40
|
+
#
|
41
|
+
#To view a copy of this license, visit
|
42
|
+
# http://creativecommons.org/licenses/by-nc/2.5/ or
|
43
|
+
#send a letter to
|
44
|
+
# Creative Commons, 543 Howard Street, 5th Floor,
|
45
|
+
# San Francisco, California, 94105, USA.
|
46
|
+
#
|
47
|
+
class TumblrCleanr
|
48
|
+
# tumblr domain name is set by login method
|
49
|
+
@domain
|
50
|
+
# email address is set by login method
|
51
|
+
@email
|
52
|
+
# password is set by login method
|
53
|
+
@password
|
54
|
+
# WWW::Mechanize agent is created in login method
|
55
|
+
@agent
|
56
|
+
# Array of tumblr postids is set by post_archive method
|
57
|
+
@postids
|
58
|
+
|
59
|
+
#Initializing TumblrCleanr will start an interactive prompt asking your your tumblr domain name, email address and password.
|
60
|
+
#domain name:: the domain name used to access your tumblr, without the http:// prefix (eg: popstar.tumblr.com)
|
61
|
+
#email address:: the email address used to login to tumblr (eg: brittney.spears@gmail.com)
|
62
|
+
#password:: the password for your tumblr account, <b>not the password for your email address</b>
|
63
|
+
#
|
64
|
+
#When the program finishes the user is prompted to press enter to quit.
|
65
|
+
#
|
66
|
+
def initialize
|
67
|
+
begin
|
68
|
+
puts "Welcome to TumblrCleanr by http://InternetDuctTape.com"
|
69
|
+
query_loop
|
70
|
+
parse_archive
|
71
|
+
clean
|
72
|
+
print "Success"
|
73
|
+
rescue Interrupt => e
|
74
|
+
puts "User pressed Ctrl-C"
|
75
|
+
rescue Exception => e
|
76
|
+
puts "#{e.class}: #{e.message}"
|
77
|
+
puts e.backtrace.join("\n")
|
78
|
+
end
|
79
|
+
puts "Press enter to exit..."
|
80
|
+
gets
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
#Keeps asking the user for their login information until they enter something that works.
|
86
|
+
#Press Ctrl-C to exit the loop (and the program).
|
87
|
+
#
|
88
|
+
def query_loop
|
89
|
+
login_success = false
|
90
|
+
while not login_success do
|
91
|
+
begin
|
92
|
+
query_user
|
93
|
+
login
|
94
|
+
login_success = true
|
95
|
+
rescue Interrupt => e
|
96
|
+
raise Interrupt, "user abort"
|
97
|
+
rescue Exception => e
|
98
|
+
puts "#{e.class}: #{e.message}"
|
99
|
+
puts e.backtrace.join("\n")
|
100
|
+
login_success = false
|
101
|
+
puts ""
|
102
|
+
puts "Unable to login with #{@email}/#{@password} on #{@domain}"
|
103
|
+
puts "Type 'Ctrl-C' to abort"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
#Asks the user for @domain, @email, and @password
|
109
|
+
#
|
110
|
+
#Side Effect:: sets @domain, @email and @password
|
111
|
+
#
|
112
|
+
def query_user
|
113
|
+
puts ""
|
114
|
+
puts "Tumblr domain (ie: popstar.tumblr.com): "
|
115
|
+
@domain = gets.chomp
|
116
|
+
puts "Tumblr email address (ie: brittney.spears@gmail.com): "
|
117
|
+
@email = gets.chomp
|
118
|
+
puts "Tumblr password (ie: kfedsux): "
|
119
|
+
@password = gets.chomp
|
120
|
+
end
|
121
|
+
|
122
|
+
#Creates a WWW::Mechanize @agent and uses it to verify that @domain is correct and
|
123
|
+
#that the @email/@password combination logs in.
|
124
|
+
#
|
125
|
+
#Side Effect:: creates @agent
|
126
|
+
#
|
127
|
+
def login
|
128
|
+
puts "Trying to connect to tumblr"
|
129
|
+
@agent = WWW::Mechanize.new do |a|
|
130
|
+
# a.log = Logger.new("mech.log")
|
131
|
+
# a.log.level = Logger::DEBUG
|
132
|
+
a.redirect_ok = true
|
133
|
+
a.user_agent_alias = 'Windows Mozilla'
|
134
|
+
end
|
135
|
+
# Is the domain any good? This will raise 404 error if bad.
|
136
|
+
@agent.get("http://#{@domain}")
|
137
|
+
# Can the user login?
|
138
|
+
page = @agent.get('http://www.tumblr.com/login')
|
139
|
+
login_form = page.forms.first
|
140
|
+
login_form.email = @email
|
141
|
+
login_form.password = @password
|
142
|
+
result = login_form.submit(login_form.buttons.first)
|
143
|
+
raise "Bad username or password" unless "Logging in..." == result.title
|
144
|
+
end
|
145
|
+
|
146
|
+
#The Tumblr API does not provide a bandwidth efficient means of getting a list of all postids
|
147
|
+
#without getting the entire posts as well.
|
148
|
+
#This is a bad hack to use the /archive page to get a list of 3000 post_ids at a time.
|
149
|
+
#It uses Net::HTTP because the post_ids which are stored as javascript, so Mechanize can't access them.
|
150
|
+
#ie: location.href='http://rubeh.tumblr.com/post/22655521
|
151
|
+
#
|
152
|
+
#Side Effect:: sets up @postids as an array of postids (as strings)
|
153
|
+
#
|
154
|
+
def parse_archive
|
155
|
+
url = URI.parse("http://#{@domain}/archive")
|
156
|
+
req = Net::HTTP::Get.new(url.path)
|
157
|
+
res = Net::HTTP.start(url.host, url.port) {|http| http.request(req) }
|
158
|
+
# with the body of the archive page, split it into chunks that have one postid each.
|
159
|
+
# use a regular expression to extract the postid
|
160
|
+
@postids = res.body.split("onclick").map{|chunk| (chunk =~ /location.href='http:\/\/[^\/]+\/post\/(\d+)/) ? $1 : nil }.reject{|i| nil == i}
|
161
|
+
end
|
162
|
+
|
163
|
+
# Using the list of @postids from parse_archive, iterate through them and send HTTP POSTs to the /delete/id action.
|
164
|
+
# It does not check that the delete occurs. As a matter of fact, it intentionally asks to redirect to a 404 to reduce
|
165
|
+
# bandwidth.
|
166
|
+
#
|
167
|
+
def clean
|
168
|
+
total_ids = @postids.size
|
169
|
+
@postids.each_with_index do |postid, i|
|
170
|
+
puts "\nDeleted #{i}/#{total_ids}" if i % 25 == 0
|
171
|
+
print "."
|
172
|
+
result = @agent.post("http://www.tumblr.com/delete", 'id' => postid, 'redirect_to' => '/404') rescue nil
|
173
|
+
# usually tumblr redirects to the dashboard after a delete happens
|
174
|
+
# I'm intentially creating a 404 because it's much less bandwidth intensive
|
175
|
+
end
|
176
|
+
puts
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
TumblrCleanr.new # appended by Rakefile
|
@@ -0,0 +1,178 @@
|
|
1
|
+
#See TumblrCleanr class for full documentation
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
# Note: not using Tumblr API because it does not support delete
|
5
|
+
# http://ruby-tumblr.rubyforge.org/
|
6
|
+
require 'mechanize' # http://mechanize.rubyforge.org/mechanize
|
7
|
+
require 'net/http' # http://www.ruby-doc.org/stdlib/libdoc/net/http/rdoc/classes/Net/HTTP.html
|
8
|
+
require 'uri'
|
9
|
+
require 'logger'
|
10
|
+
|
11
|
+
#== TumblrCleanr - clean/reset your tumblr by deleting all posts
|
12
|
+
#Author:: engtech (http://InternetDuctTape.com, http://rubeh.tumblr.com)
|
13
|
+
#Copyright:: Copyright (c) 2008 engtech
|
14
|
+
#License:: Creative Commons Attribution-Noncommercial 2.5 License
|
15
|
+
#
|
16
|
+
#Tumblr is rapidly becoming my favorite hosted blogging platform (more so than Blogger/WordPress.com) because of all the things they do correct:
|
17
|
+
#
|
18
|
+
#- RSS feed importing
|
19
|
+
#- free domain name support
|
20
|
+
#- free CSS/theme support
|
21
|
+
#- Google Analytics support
|
22
|
+
#- keeping it simple
|
23
|
+
#
|
24
|
+
#However, there's one feature that's missing: <b>how do you delete your Tumblr?</b> At some point you might want to destroy all traces of your tumblr (privacy concerns, or you want to use it for something else) and there isn't an option to do that -- other than click the delete button on every individual post. I wanted to repurpose a tumblr I had been using for feed aggregation and it had over 18,000 posts. That's a lot of clicks.
|
25
|
+
#
|
26
|
+
#Enter the TumblrCleanr. Provide it with your tumblr domain name as well as your username and password and it will delete up to the latest 3000 posts at a time. You can keep running it until your entire tumblr is clean as a whistle.
|
27
|
+
#
|
28
|
+
#== Privacy Concerns
|
29
|
+
#
|
30
|
+
#TumblrCleanr does not store your login information anywhere and only uses it to communicate with tumblr.com. Every time you run the program you will have to re-enter your login details.
|
31
|
+
#
|
32
|
+
#== Why Not Create a New Tumblr?
|
33
|
+
#
|
34
|
+
#That's true, it's much easier to create a new tumblr account with a different email address than it is to "reset" your existing Tumblr. You can even just change the tumblr domain name if you want to "free up" your good domain for something else. I created this more for my own learning process, because I wanted to try WWW::Mechanize, rdoc, rake and rubyscript2exe for the first time and give myself some more experience coding in Ruby.
|
35
|
+
#
|
36
|
+
#== License
|
37
|
+
#
|
38
|
+
#This work is licensed under the Creative Commons
|
39
|
+
#Attribution-Noncommercial 2.5 License.
|
40
|
+
#
|
41
|
+
#To view a copy of this license, visit
|
42
|
+
# http://creativecommons.org/licenses/by-nc/2.5/ or
|
43
|
+
#send a letter to
|
44
|
+
# Creative Commons, 543 Howard Street, 5th Floor,
|
45
|
+
# San Francisco, California, 94105, USA.
|
46
|
+
#
|
47
|
+
class TumblrCleanr
|
48
|
+
# tumblr domain name is set by login method
|
49
|
+
@domain
|
50
|
+
# email address is set by login method
|
51
|
+
@email
|
52
|
+
# password is set by login method
|
53
|
+
@password
|
54
|
+
# WWW::Mechanize agent is created in login method
|
55
|
+
@agent
|
56
|
+
# Array of tumblr postids is set by post_archive method
|
57
|
+
@postids
|
58
|
+
|
59
|
+
#Initializing TumblrCleanr will start an interactive prompt asking your your tumblr domain name, email address and password.
|
60
|
+
#domain name:: the domain name used to access your tumblr, without the http:// prefix (eg: popstar.tumblr.com)
|
61
|
+
#email address:: the email address used to login to tumblr (eg: brittney.spears@gmail.com)
|
62
|
+
#password:: the password for your tumblr account, <b>not the password for your email address</b>
|
63
|
+
#
|
64
|
+
#When the program finishes the user is prompted to press enter to quit.
|
65
|
+
#
|
66
|
+
def initialize
|
67
|
+
begin
|
68
|
+
puts "Welcome to TumblrCleanr by http://InternetDuctTape.com"
|
69
|
+
query_loop
|
70
|
+
parse_archive
|
71
|
+
clean
|
72
|
+
print "Success"
|
73
|
+
rescue Interrupt => e
|
74
|
+
puts "User pressed Ctrl-C"
|
75
|
+
rescue Exception => e
|
76
|
+
puts "#{e.class}: #{e.message}"
|
77
|
+
puts e.backtrace.join("\n")
|
78
|
+
end
|
79
|
+
puts "Press enter to exit..."
|
80
|
+
gets
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
#Keeps asking the user for their login information until they enter something that works.
|
86
|
+
#Press Ctrl-C to exit the loop (and the program).
|
87
|
+
#
|
88
|
+
def query_loop
|
89
|
+
login_success = false
|
90
|
+
while not login_success do
|
91
|
+
begin
|
92
|
+
query_user
|
93
|
+
login
|
94
|
+
login_success = true
|
95
|
+
rescue Interrupt => e
|
96
|
+
raise Interrupt, "user abort"
|
97
|
+
rescue Exception => e
|
98
|
+
puts "#{e.class}: #{e.message}"
|
99
|
+
puts e.backtrace.join("\n")
|
100
|
+
login_success = false
|
101
|
+
puts ""
|
102
|
+
puts "Unable to login with #{@email}/#{@password} on #{@domain}"
|
103
|
+
puts "Type 'Ctrl-C' to abort"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
#Asks the user for @domain, @email, and @password
|
109
|
+
#
|
110
|
+
#Side Effect:: sets @domain, @email and @password
|
111
|
+
#
|
112
|
+
def query_user
|
113
|
+
puts ""
|
114
|
+
puts "Tumblr domain (ie: popstar.tumblr.com): "
|
115
|
+
@domain = gets.chomp
|
116
|
+
puts "Tumblr email address (ie: brittney.spears@gmail.com): "
|
117
|
+
@email = gets.chomp
|
118
|
+
puts "Tumblr password (ie: kfedsux): "
|
119
|
+
@password = gets.chomp
|
120
|
+
end
|
121
|
+
|
122
|
+
#Creates a WWW::Mechanize @agent and uses it to verify that @domain is correct and
|
123
|
+
#that the @email/@password combination logs in.
|
124
|
+
#
|
125
|
+
#Side Effect:: creates @agent
|
126
|
+
#
|
127
|
+
def login
|
128
|
+
puts "Trying to connect to tumblr"
|
129
|
+
@agent = WWW::Mechanize.new do |a|
|
130
|
+
# a.log = Logger.new("mech.log")
|
131
|
+
# a.log.level = Logger::DEBUG
|
132
|
+
a.redirect_ok = true
|
133
|
+
a.user_agent_alias = 'Windows Mozilla'
|
134
|
+
end
|
135
|
+
# Is the domain any good? This will raise 404 error if bad.
|
136
|
+
@agent.get("http://#{@domain}")
|
137
|
+
# Can the user login?
|
138
|
+
page = @agent.get('http://www.tumblr.com/login')
|
139
|
+
login_form = page.forms.first
|
140
|
+
login_form.email = @email
|
141
|
+
login_form.password = @password
|
142
|
+
result = login_form.submit(login_form.buttons.first)
|
143
|
+
raise "Bad username or password" unless "Logging in..." == result.title
|
144
|
+
end
|
145
|
+
|
146
|
+
#The Tumblr API does not provide a bandwidth efficient means of getting a list of all postids
|
147
|
+
#without getting the entire posts as well.
|
148
|
+
#This is a bad hack to use the /archive page to get a list of 3000 post_ids at a time.
|
149
|
+
#It uses Net::HTTP because the post_ids which are stored as javascript, so Mechanize can't access them.
|
150
|
+
#ie: location.href='http://rubeh.tumblr.com/post/22655521
|
151
|
+
#
|
152
|
+
#Side Effect:: sets up @postids as an array of postids (as strings)
|
153
|
+
#
|
154
|
+
def parse_archive
|
155
|
+
url = URI.parse("http://#{@domain}/archive")
|
156
|
+
req = Net::HTTP::Get.new(url.path)
|
157
|
+
res = Net::HTTP.start(url.host, url.port) {|http| http.request(req) }
|
158
|
+
# with the body of the archive page, split it into chunks that have one postid each.
|
159
|
+
# use a regular expression to extract the postid
|
160
|
+
@postids = res.body.split("onclick").map{|chunk| (chunk =~ /location.href='http:\/\/[^\/]+\/post\/(\d+)/) ? $1 : nil }.reject{|i| nil == i}
|
161
|
+
end
|
162
|
+
|
163
|
+
# Using the list of @postids from parse_archive, iterate through them and send HTTP POSTs to the /delete/id action.
|
164
|
+
# It does not check that the delete occurs. As a matter of fact, it intentionally asks to redirect to a 404 to reduce
|
165
|
+
# bandwidth.
|
166
|
+
#
|
167
|
+
def clean
|
168
|
+
total_ids = @postids.size
|
169
|
+
@postids.each_with_index do |postid, i|
|
170
|
+
puts "\nDeleted #{i}/#{total_ids}" if i % 25 == 0
|
171
|
+
print "."
|
172
|
+
result = @agent.post("http://www.tumblr.com/delete", 'id' => postid, 'redirect_to' => '/404') rescue nil
|
173
|
+
# usually tumblr redirects to the dashboard after a delete happens
|
174
|
+
# I'm intentially creating a 404 because it's much less bandwidth intensive
|
175
|
+
end
|
176
|
+
puts
|
177
|
+
end
|
178
|
+
end
|
metadata
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.4
|
3
|
+
specification_version: 1
|
4
|
+
name: tumblr_cleanr
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.0.1
|
7
|
+
date: 2008-02-25 00:00:00 -05:00
|
8
|
+
summary: Script for deleting your tumblr account
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: engtechnology+tumblrcleanr@gmail.com
|
12
|
+
homepage:
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire: tumblr_cleanr
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- engtech
|
31
|
+
files:
|
32
|
+
- bin/tumblr_cleanr.rb
|
33
|
+
- lib/tumblr_cleanr.rb
|
34
|
+
- README
|
35
|
+
test_files: []
|
36
|
+
|
37
|
+
rdoc_options: []
|
38
|
+
|
39
|
+
extra_rdoc_files:
|
40
|
+
- README
|
41
|
+
executables: []
|
42
|
+
|
43
|
+
extensions: []
|
44
|
+
|
45
|
+
requirements: []
|
46
|
+
|
47
|
+
dependencies: []
|
48
|
+
|