tumblr 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: