tumblr 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. data/a.rb +12 -0
  2. data/bin/tumblr +181 -0
  3. data/gemspec.rb +36 -0
  4. data/install.rb +212 -0
  5. data/lib/tumblr.rb +142 -0
  6. metadata +78 -0
data/a.rb ADDED
@@ -0,0 +1,12 @@
1
+ require 'tumblr'
2
+
3
+ name, email, password, *ignored = ARGV
4
+
5
+ tumblr = Tumblr.for :name => name,
6
+ :email => email,
7
+ :password => password
8
+
9
+ [:authenticate, :check_vimeo, :check_audio].each do |m|
10
+ response = tumblr.send m
11
+ p response
12
+ end
data/bin/tumblr ADDED
@@ -0,0 +1,181 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require "tumblr"
4
+
5
+ Main {
6
+ description <<-txt
7
+ tumblr.rb is a command line utility and library which interfaces to the
8
+ excellent tumblr blogging platform @ http://www.tumblr.com
9
+
10
+ tumblr.rb implements the complete restful api in both library and
11
+ command line utility, doccumented in full @ http://www.tumblr.com/api
12
+
13
+ === install ===
14
+
15
+ gem install tumblr
16
+
17
+ === cli ===
18
+
19
+ the cli exactly mirrors the library api. arguments are passed to each
20
+ method as 'key=val' pairs, values may be read from files using the
21
+ syntax 'key=file=val' or 'key==val'
22
+
23
+ you should first cache your login info to avoid having to pass it everytime
24
+
25
+ cfp: ~> tumblr setup --email=my_email --password=my_password --name=drawohara
26
+ /Users/ahoward/.tumblr.yml
27
+
28
+ you can post
29
+
30
+ cfp: ~> tumblr write regular title=testing body=rock_on
31
+
32
+ you can post from files
33
+
34
+ cfp: ~> tumblr write regular title=slurp body==./post.html
35
+
36
+ you can read
37
+
38
+ cfp: ~> tumblr read start=42 num=42
39
+
40
+ you can test the auth
41
+
42
+ cfp: ~> tumblr authenticate
43
+
44
+ etc.
45
+
46
+ === api ===
47
+
48
+ it's pretty simple. here's a start, use the web docs to figure out the
49
+ rest
50
+
51
+ config = {
52
+ :email => my_email,
53
+ :password => my_password,
54
+ :name => 'drawohara'
55
+ }
56
+
57
+ tumblr = Tumblr.for config
58
+
59
+ abort unless tumblr.uri == 'http://drawohara.tumblr.com'
60
+
61
+ response = tumblr.write :regular, :title = title, :body => body
62
+
63
+ video = open 'video.mpg'
64
+ response = tumblr.write :video, :data => video, :title => video.path
65
+
66
+ response = tumblr.read :start => 42, :num => 42
67
+ xml = response.content
68
+
69
+ response = tumblr.read :start => 42, :num => 42, :json => true
70
+ json = response.content
71
+ txt
72
+
73
+ alias_method "run", "help!"
74
+
75
+ option("name", "n"){ argument_required }
76
+ option("email", "e"){ argument_required }
77
+ option("password", "p"){ argument_required }
78
+ option("debug", "d"){ }
79
+ option("json", "j"){ }
80
+
81
+ def home
82
+ ENV["HOME"] || ENV["HOMEPATH"] || File::expand_path("~")
83
+ end
84
+
85
+ def configfile
86
+ File.join home, ".tumblr.yml"
87
+ end
88
+
89
+ def parse_args
90
+ hash = { 'json' => params['json'].value }
91
+ argv.inject hash do |args, arg|
92
+ k, v = arg.split %r/=/, 2
93
+ if v[%r/^(?:file|path)?=/]
94
+ file, v = v.split %r/=/, 2
95
+ v = v == '-' ? STDIN.read : IO.read(v)
96
+ end
97
+ v ||= true
98
+ args.update k => v
99
+ end
100
+ end
101
+
102
+ def config
103
+ @config ||= (
104
+ h = test(?e, configfile) ? YAML.load(IO.read(configfile)) : Hash.new
105
+ %w[ name email password ].each do |k|
106
+ h[k] = params[k].value if params[k].given?
107
+ end
108
+ h['debug'] = STDERR if params["debug"].given?
109
+ h
110
+ )
111
+ end
112
+
113
+ def tumblr
114
+ Tumblr.for config
115
+ end
116
+
117
+ def handle response
118
+ unless Tumblr.successful?(response)
119
+ STDERR.puts response.status
120
+ STDOUT.puts response.content
121
+ exit 1
122
+ else
123
+ STDOUT.puts response.content
124
+ end
125
+ end
126
+
127
+ mode "setup" do
128
+ option("name", "n"){ argument_required and required }
129
+ option("email", "e"){ argument_required and required }
130
+ option("password", "p"){ argument_required and required }
131
+
132
+ def run
133
+ keys = %w[ name email password ]
134
+ conf = keys.inject({}) do |h,k|
135
+ raise "#{ k } not given" unless params[k].given?
136
+ h.update k => params[k].value
137
+ end
138
+ open(configfile, "w"){|fd| fd.write conf.to_yaml}
139
+ tumblr.authenticate
140
+ puts configfile
141
+ end
142
+ end
143
+
144
+ mode "write" do
145
+ def run
146
+ handle tumblr.write(mode, parse_args)
147
+ end
148
+
149
+ mode "regular"
150
+ mode "photo"
151
+ mode "quote"
152
+ mode "link"
153
+ mode "conversation"
154
+ mode "video"
155
+ mode "audio"
156
+ end
157
+
158
+ mode "read" do
159
+ def run
160
+ handle tumblr.read(mode, parse_args)
161
+ end
162
+ end
163
+
164
+ mode "authenticate" do
165
+ def run
166
+ handle tumblr.authenticate
167
+ end
168
+ end
169
+
170
+ mode "check-vimeo" do
171
+ def run
172
+ handle tumblr.check_vimeo
173
+ end
174
+ end
175
+
176
+ mode "check-audio" do
177
+ def run
178
+ handle tumblr.check_audio
179
+ end
180
+ end
181
+ }
data/gemspec.rb ADDED
@@ -0,0 +1,36 @@
1
+ lib, version = File::basename(File::dirname(File::expand_path(__FILE__))).split %r/-/, 2
2
+
3
+ require 'rubygems'
4
+
5
+ Gem::Specification::new do |spec|
6
+ $VERBOSE = nil
7
+
8
+ shiteless = lambda do |list|
9
+ list.delete_if do |file|
10
+ file =~ %r/\.svn/ or file =~ %r/\.tmp/
11
+ end
12
+ end
13
+
14
+ spec.name = lib
15
+ spec.version = version
16
+ spec.platform = Gem::Platform::RUBY
17
+ spec.summary = lib
18
+
19
+ spec.files = shiteless[Dir::glob("**/**")]
20
+ spec.executables = shiteless[Dir::glob("bin/*")].map{|exe| File::basename exe}
21
+
22
+ spec.require_path = "lib"
23
+ spec.autorequire = lib
24
+
25
+ spec.has_rdoc = File::exist? "doc"
26
+ spec.test_suite_file = "test/#{ lib }.rb" if File::directory? "test"
27
+ spec.add_dependency 'main', '>= 2.5.0'
28
+ spec.add_dependency 'attributes', '>= 4.1.0'
29
+ spec.add_dependency 'httpclient', '>= 2.1.2' # rock on NaHi
30
+
31
+ spec.extensions << "extconf.rb" if File::exists? "extconf.rb"
32
+
33
+ spec.author = "Ara T. Howard"
34
+ spec.email = "ara.t.howard@gmail.com"
35
+ spec.homepage = "http://codeforpeople.com/lib/ruby/#{ lib }/"
36
+ end
data/install.rb ADDED
@@ -0,0 +1,212 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rbconfig'
3
+ require 'find'
4
+ require 'ftools'
5
+ require 'tempfile'
6
+ include Config
7
+
8
+ LIBDIR = "lib"
9
+ LIBDIR_MODE = 0644
10
+
11
+ BINDIR = "bin"
12
+ BINDIR_MODE = 0755
13
+
14
+
15
+ $srcdir = CONFIG["srcdir"]
16
+ $version = CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
17
+ $libdir = File.join(CONFIG["libdir"], "ruby", $version)
18
+ $archdir = File.join($libdir, CONFIG["arch"])
19
+ $site_libdir = $:.find {|x| x =~ /site_ruby$/}
20
+ $bindir = CONFIG["bindir"] || CONFIG['BINDIR']
21
+ $ruby_install_name = CONFIG['ruby_install_name'] || CONFIG['RUBY_INSTALL_NAME'] || 'ruby'
22
+ $ruby_ext = CONFIG['EXEEXT'] || ''
23
+ $ruby = File.join($bindir, ($ruby_install_name + $ruby_ext))
24
+
25
+ if !$site_libdir
26
+ $site_libdir = File.join($libdir, "site_ruby")
27
+ elsif $site_libdir !~ %r/#{Regexp.quote($version)}/
28
+ $site_libdir = File.join($site_libdir, $version)
29
+ end
30
+
31
+ def install_rb(srcdir=nil, destdir=nil, mode=nil, bin=nil)
32
+ #{{{
33
+ path = []
34
+ dir = []
35
+ Find.find(srcdir) do |f|
36
+ next unless FileTest.file?(f)
37
+ next if (f = f[srcdir.length+1..-1]) == nil
38
+ next if (/CVS$/ =~ File.dirname(f))
39
+ next if f =~ %r/\.lnk/
40
+ next if f =~ %r/\.svn/
41
+ next if f =~ %r/\.swp/
42
+ path.push f
43
+ dir |= [File.dirname(f)]
44
+ end
45
+ for f in dir
46
+ next if f == "."
47
+ next if f == "CVS"
48
+ File::makedirs(File.join(destdir, f))
49
+ end
50
+ for f in path
51
+ next if (/\~$/ =~ f)
52
+ next if (/^\./ =~ File.basename(f))
53
+ unless bin
54
+ File::install(File.join(srcdir, f), File.join(destdir, f), mode, true)
55
+ else
56
+ from = File.join(srcdir, f)
57
+ to = File.join(destdir, f)
58
+ shebangify(from) do |sf|
59
+ $deferr.print from, " -> ", File::catname(from, to), "\n"
60
+ $deferr.printf "chmod %04o %s\n", mode, to
61
+ File::install(sf, to, mode, false)
62
+ end
63
+ end
64
+ end
65
+ #}}}
66
+ end
67
+ def shebangify f
68
+ #{{{
69
+ open(f) do |fd|
70
+ buf = fd.read 42
71
+ if buf =~ %r/^\s*#\s*!.*ruby/o
72
+ ftmp = Tempfile::new("#{ $$ }_#{ File::basename(f) }")
73
+ begin
74
+ fd.rewind
75
+ ftmp.puts "#!#{ $ruby }"
76
+ while((buf = fd.read(8192)))
77
+ ftmp.write buf
78
+ end
79
+ ftmp.close
80
+ yield ftmp.path
81
+ ensure
82
+ ftmp.close!
83
+ end
84
+ else
85
+ yield f
86
+ end
87
+ end
88
+ #}}}
89
+ end
90
+ def ARGV.switch
91
+ #{{{
92
+ return nil if self.empty?
93
+ arg = self.shift
94
+ return nil if arg == '--'
95
+ if arg =~ /^-(.)(.*)/
96
+ return arg if $1 == '-'
97
+ raise 'unknown switch "-"' if $2.index('-')
98
+ self.unshift "-#{$2}" if $2.size > 0
99
+ "-#{$1}"
100
+ else
101
+ self.unshift arg
102
+ nil
103
+ end
104
+ #}}}
105
+ end
106
+ def ARGV.req_arg
107
+ #{{{
108
+ self.shift || raise('missing argument')
109
+ #}}}
110
+ end
111
+ def linkify d, linked = []
112
+ #--{{{
113
+ if test ?d, d
114
+ versioned = Dir[ File::join(d, "*-[0-9].[0-9].[0-9].rb") ]
115
+ versioned.each do |v|
116
+ src, dst = v, v.gsub(%r/\-[\d\.]+\.rb$/, '.rb')
117
+ lnk = nil
118
+ begin
119
+ if test ?l, dst
120
+ lnk = "#{ dst }.lnk"
121
+ puts "#{ dst } -> #{ lnk }"
122
+ File::rename dst, lnk
123
+ end
124
+ unless test ?e, dst
125
+ puts "#{ src } -> #{ dst }"
126
+ File::copy src, dst
127
+ linked << dst
128
+ end
129
+ ensure
130
+ if lnk
131
+ at_exit do
132
+ puts "#{ lnk } -> #{ dst }"
133
+ File::rename lnk, dst
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
139
+ linked
140
+ #--}}}
141
+ end
142
+
143
+
144
+ #
145
+ # main program
146
+ #
147
+
148
+ libdir = $site_libdir
149
+ bindir = $bindir
150
+ no_linkify = false
151
+ linked = nil
152
+ help = false
153
+
154
+ usage = <<-usage
155
+ #{ File::basename $0 }
156
+ -d, --destdir <destdir>
157
+ -l, --libdir <libdir>
158
+ -b, --bindir <bindir>
159
+ -r, --ruby <ruby>
160
+ -n, --no_linkify
161
+ -s, --sudo
162
+ -h, --help
163
+ usage
164
+
165
+ begin
166
+ while switch = ARGV.switch
167
+ case switch
168
+ when '-d', '--destdir'
169
+ libdir = ARGV.req_arg
170
+ when '-l', '--libdir'
171
+ libdir = ARGV.req_arg
172
+ when '-b', '--bindir'
173
+ bindir = ARGV.req_arg
174
+ when '-r', '--ruby'
175
+ $ruby = ARGV.req_arg
176
+ when '-n', '--no_linkify'
177
+ no_linkify = true
178
+ when '-s', '--sudo'
179
+ sudo = 'sudo'
180
+ when '-h', '--help'
181
+ help = true
182
+ else
183
+ raise "unknown switch #{switch.dump}"
184
+ end
185
+ end
186
+ rescue
187
+ STDERR.puts $!.to_s
188
+ STDERR.puts usage
189
+ exit 1
190
+ end
191
+
192
+ if help
193
+ STDOUT.puts usage
194
+ exit
195
+ end
196
+
197
+ system "#{ sudo } #{ $ruby } pre-install.rb" if test(?s, 'pre-install.rb')
198
+
199
+ unless no_linkify
200
+ linked = linkify('lib') + linkify('bin')
201
+ end
202
+
203
+ system "#{ $ruby } extconf.rb && make && #{ sudo } make install" if test(?s, 'extconf.rb')
204
+
205
+ install_rb(LIBDIR, libdir, LIBDIR_MODE)
206
+ install_rb(BINDIR, bindir, BINDIR_MODE, bin=true)
207
+
208
+ if linked
209
+ linked.each{|path| File::rm_f path}
210
+ end
211
+
212
+ system "#{ sudo } #{ $ruby } post-install.rb" if test(?s, 'post-install.rb')
data/lib/tumblr.rb ADDED
@@ -0,0 +1,142 @@
1
+ #
2
+ # gems
3
+ #
4
+ begin
5
+ gem "main", ">= 2.5.0"
6
+ gem "attributes", ">= 4.1.0"
7
+ gem "httpclient", ">= 2.1.2"
8
+ rescue Exception
9
+ 42
10
+ end
11
+ require "main"
12
+ require "attributes"
13
+ require "httpclient"
14
+ #
15
+ # built-in
16
+ #
17
+ require "uri"
18
+ require "yaml"
19
+ #
20
+ # tumblr.rb
21
+ #
22
+ module Tumblr
23
+ def self.for *a, &b
24
+ Account.new *a, &b
25
+ end
26
+
27
+ class Account
28
+ attribute "name"
29
+ attribute "email"
30
+ attribute "password"
31
+ attribute "debug"
32
+ attribute("uri"){ "http://#{ name }.tumblr.com" }
33
+ attribute("generator"){ "tumblr.rb" }
34
+ attribute("proxy"){ ENV["HTTP_PROXY"] }
35
+ attribute("httpclient"){ HTTPClient.new proxy }
36
+ attribute("api"){ API.new "account" => account }
37
+ attribute("account"){ self }
38
+
39
+ def initialize options = {}
40
+ options.each{|k,v| send k, v}
41
+ httpclient.debug_dev = debug if debug?
42
+ end
43
+
44
+ def options
45
+ {
46
+ 'email' => email,
47
+ 'password' => password,
48
+ 'generator' => generator,
49
+ }
50
+ end
51
+
52
+ def method_missing m, *a, &b
53
+ super unless api.respond_to? m
54
+ api.send m, *a, &b
55
+ end
56
+ end
57
+
58
+ class API
59
+ attribute "account"
60
+ attribute("uri"){ "#{ account.uri }/api" }
61
+ attribute("uri_write"){ "#{ uri }/write" }
62
+ attribute("uri_read"){ "#{ uri }/read" }
63
+ attribute("uri_read_json"){ "#{ uri }/read/json" }
64
+
65
+ def initialize options = {}
66
+ options.each{|k,v| send k, v}
67
+ end
68
+
69
+ def write type, options = {}
70
+ json = options.delete('json') || options.delete(:json)
71
+ uri = uri_write
72
+ post uri, options.merge(account.options).merge('type' => type)
73
+ end
74
+
75
+ def read type, options = {}
76
+ json = options.delete('json') || options.delete(:json)
77
+ uri = json ? uri_read_json : uri_read
78
+ get uri, options.merge(account.options)
79
+ end
80
+
81
+ def authenticate options = {}
82
+ post uri_write,
83
+ options.merge(account.options).merge('action' => 'authenticate')
84
+ end
85
+
86
+ def check_vimeo options = {}
87
+ post uri_write,
88
+ options.merge(account.options).merge('action' => 'check-vimeo')
89
+ end
90
+
91
+ def check_audio options = {}
92
+ post uri_write,
93
+ options.merge(account.options).merge('action' => 'check-audio')
94
+ end
95
+
96
+ def post uri, options = {}
97
+ following_redirects(uri, options) do |uri, options|
98
+ account.httpclient.post uri, options, "content-type" => boundary
99
+ end
100
+ end
101
+
102
+ def get uri, options = {}
103
+ following_redirects(uri, options) do |uri, options|
104
+ account.httpclient.get uri, options
105
+ end
106
+ end
107
+
108
+ def boundary
109
+ random = Array::new(8){ "%2.2d" % rand(42) }.join("__")
110
+ "multipart/form-data; boundary=___#{ random }___"
111
+ end
112
+
113
+ def following_redirects uri, options = {}
114
+ 42.times do
115
+ res = yield uri, options
116
+ if HTTP::Status.successful?(res.status)
117
+ return res
118
+ elsif HTTP::Status.redirect?(res.status)
119
+ uri = handle_redirect uri, res
120
+ else
121
+ return res
122
+ end
123
+ end
124
+ raise "followed too damn many redirects!"
125
+ end
126
+
127
+ def handle_redirect uri, res
128
+ newuri = URI.parse res.header['location'][0]
129
+ newuri = uri + newuri unless newuri.is_a?(URI::HTTP)
130
+ newuri
131
+ end
132
+
133
+ def self.successful? res
134
+ HTTP::Status.successful? res.status
135
+ end
136
+ end
137
+
138
+ def self.successful? status
139
+ status = status.status rescue status
140
+ HTTP::Status.successful? status
141
+ end
142
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.2
3
+ specification_version: 1
4
+ name: tumblr
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.0.1
7
+ date: 2007-11-02 00:00:00 -06:00
8
+ summary: tumblr
9
+ require_paths:
10
+ - lib
11
+ email: ara.t.howard@gmail.com
12
+ homepage: http://codeforpeople.com/lib/ruby/tumblr/
13
+ rubyforge_project:
14
+ description:
15
+ autorequire: tumblr
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: false
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
+ - Ara T. Howard
31
+ files:
32
+ - a.rb
33
+ - bin
34
+ - bin/tumblr
35
+ - gemspec.rb
36
+ - install.rb
37
+ - lib
38
+ - lib/tumblr.rb
39
+ test_files: []
40
+
41
+ rdoc_options: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ executables:
46
+ - tumblr
47
+ extensions: []
48
+
49
+ requirements: []
50
+
51
+ dependencies:
52
+ - !ruby/object:Gem::Dependency
53
+ name: main
54
+ version_requirement:
55
+ version_requirements: !ruby/object:Gem::Version::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: 2.5.0
60
+ version:
61
+ - !ruby/object:Gem::Dependency
62
+ name: attributes
63
+ version_requirement:
64
+ version_requirements: !ruby/object:Gem::Version::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 4.1.0
69
+ version:
70
+ - !ruby/object:Gem::Dependency
71
+ name: httpclient
72
+ version_requirement:
73
+ version_requirements: !ruby/object:Gem::Version::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: 2.1.2
78
+ version: