squarepusher 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ squarepusher downloads Flickr photosets to your local hard disk.
2
+
3
+ if you are using rubygems, get started with:
4
+ `gem install squarepusher`
5
+
6
+ you can easily start by creating a file ~/.squarepusher.yaml with this content:
7
+
8
+ key: consumer key
9
+ secret: consumer secret
10
+ token: access token
11
+ token_secret: access token secret
12
+
13
+ then run `squarepusher` with the action that you're interested in, foe example:
14
+
15
+ `squarepusher list_sets`
16
+
17
+ lists all of your flickr photosets.
18
+
19
+ there are a few different ways to generate an access token. assuming you have a consumer key, here is one way:
20
+ [http://www.flickr.com/services/api/auth.howto.mobile.html](http://www.flickr.com/services/api/auth.howto.mobile.html "flickr mobile auth instructions")
21
+
22
+ dependencies:
23
+
24
+ * [flickraw](https://github.com/hanklords/flickraw "flickraw")
25
+
26
+
27
+ behaviors of note:
28
+
29
+ * photoset and image names are normalized using this: `name.gsub(/[^\w_+\.=-]+/, '-')`
data/bin/squarepusher CHANGED
@@ -3,91 +3,118 @@
3
3
  require 'rubygems'
4
4
  require 'squarepusher'
5
5
 
6
- def error_msg(msg)
7
- $stderr.puts "ERROR - #{msg}"
8
- end
6
+ Squarepusher::CLI.main
9
7
 
10
- def fail(msg, code=1)
11
- error_msg(msg)
12
- exit code
13
- end
14
-
15
-
16
- actions = {}
17
-
18
- actions[:list_sets] = lambda do |client, args|
19
- client.each_photoset do |pset|
20
- puts Squarepusher.describe_photoset(pset)
21
- end
22
- end
23
-
24
- actions[:grab_all_sets] = lambda do |client, args|
25
- if not args
26
- fail("expected: <output_dir>")
27
- end
28
-
29
- client.each_photoset do |pset|
30
- puts Squarepusher.describe_photoset(pset)
31
- results = client.download_photoset(pset, output_dir)
32
- puts results.inspect
33
- end
34
- end
35
-
36
- actions[:grab_set] = lambda do |client, args|
37
- if args.size != 2
38
- fail("expected: <photoset_id> <output_dir>")
39
- end
40
-
41
- pset_id, output_dir = args
42
- pset = client.get_photoset(pset_id)
43
- client.download_photoset(pset, output_dir)
44
- end
45
-
46
- actions[:find_set] = lambda do |client, args|
47
- if args.size != 1
48
- fail("expected: <photoset_id>")
49
- end
50
-
51
- pset_id, output_dir = args
52
- pset = client.get_photoset(pset_id)
53
- puts Squarepusher.describe_photoset(pset)
54
- end
55
-
56
-
57
- def action_str(actions)
58
- actions.keys.join(", ")
59
- end
60
-
61
-
62
- options = { :size => :original }
63
- args = nil
64
- action = nil
65
- client = nil
66
- OptionParser.new do |opts|
67
- opts.banner = "USAGE: squarepusher [options] <api-key> <api-secret> <token> <action:(#{action_str(actions)})> [args]"
68
-
69
- # TODO: list sizing options
70
- opts.on("-s", "--size SIZE", "size of photos to download (using flickr terminology)") do |v|
71
- options[:size] = v.to_sym
72
- end
73
-
74
- opts.parse!(ARGV)
75
-
76
- if ARGV.size < 4
77
- $stderr.puts opts
78
- exit 1
79
- end
80
-
81
- key, secret, token, action = ARGV.slice!(0...4)
82
- args = ARGV
83
-
84
- action = action.to_sym
85
- if not actions.has_key?(action)
86
- $stderr.puts opts
87
- exit 2
88
- end
89
-
90
- client = Squarepusher::Client.new(key, secret, token, options)
91
- end
92
-
93
- actions[action].call(client, args || [])
8
+ # require 'rubygems'
9
+ # require 'squarepusher'
10
+ #
11
+ # def error_msg(msg)
12
+ # $stderr.puts "ERROR - #{msg}"
13
+ # end
14
+ #
15
+ # def fail(msg, code=1)
16
+ # error_msg(msg)
17
+ # exit code
18
+ # end
19
+ #
20
+ #
21
+ # actions = {}
22
+ #
23
+ # actions[:list_sets] = lambda do |client, args|
24
+ # client.each_photoset do |pset|
25
+ # puts Squarepusher.describe_photoset(pset)
26
+ # end
27
+ # end
28
+ #
29
+ # actions[:grab_all_sets] = lambda do |client, args|
30
+ # if args.size != 1
31
+ # fail("expected: <output_dir>")
32
+ # end
33
+ #
34
+ # output_dir = args[0]
35
+ #
36
+ # total_results = {}
37
+ # client.each_photoset do |pset|
38
+ # pset_description = Squarepusher.describe_photoset(pset)
39
+ # puts "[set] #{pset_description}"
40
+ # pset_results = client.download_photoset(pset, output_dir)
41
+ # puts "[results] #{pset_description} #{pset_results.inspect}"
42
+ # total_results[pset_description] = pset_results
43
+ # puts
44
+ # end
45
+ #
46
+ # total_results.each_pair do |k, v|
47
+ # puts "#{k}: #{v.inspect}"
48
+ # end
49
+ # end
50
+ #
51
+ # actions[:grab_set] = lambda do |client, args|
52
+ # if args.size != 2
53
+ # fail("expected: <photoset_id> <output_dir>")
54
+ # end
55
+ #
56
+ # pset_id, output_dir = args
57
+ # pset = client.get_photoset(pset_id)
58
+ # results = client.download_photoset(pset, output_dir)
59
+ # puts results.inspect
60
+ # end
61
+ #
62
+ # actions[:find_set] = lambda do |client, args|
63
+ # if args.size != 1
64
+ # fail("expected: <photoset_id>")
65
+ # end
66
+ #
67
+ # pset_id, output_dir = args
68
+ # pset = client.get_photoset(pset_id)
69
+ # puts Squarepusher.describe_photoset(pset)
70
+ # end
71
+ #
72
+ #
73
+ # def action_str(actions)
74
+ # actions.keys.join(",")
75
+ # end
76
+ #
77
+ # def size_str
78
+ # Squarepusher.sizes.join(",")
79
+ # end
80
+ #
81
+ #
82
+ # options = { :size => :original }
83
+ # args = nil
84
+ # action = nil
85
+ # client = nil
86
+ # OptionParser.new do |opts|
87
+ # opts.banner = "USAGE: squarepusher [options] <api-key> <api-secret> <token> <action:(#{action_str(actions)})> [args]"
88
+ #
89
+ # opts.on("-o", "--overwrite", "overwrite already downloaded files") do |v|
90
+ # options[:overwrite] = v
91
+ # end
92
+ #
93
+ # opts.on("-s", "--size SIZE", "size of photos to download (#{size_str()})") do |v|
94
+ # options[:size] = v.to_sym
95
+ # end
96
+ #
97
+ # opts.on("-v", "--verbose", "log verbosely") do |v|
98
+ # options[:verbose] = v
99
+ # end
100
+ #
101
+ # opts.parse!(ARGV)
102
+ #
103
+ # if ARGV.size < 4
104
+ # $stderr.puts opts
105
+ # exit 1
106
+ # end
107
+ #
108
+ # key, secret, token, action = ARGV.slice!(0...4)
109
+ # args = ARGV
110
+ #
111
+ # action = action.to_sym
112
+ # if not actions.has_key?(action)
113
+ # $stderr.puts opts
114
+ # exit 2
115
+ # end
116
+ #
117
+ # client = Squarepusher::Client.new(key, secret, token, options)
118
+ # end
119
+ #
120
+ # actions[action].call(client, args || [])
@@ -0,0 +1,167 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'yaml'
4
+
5
+
6
+ module Squarepusher
7
+
8
+ class CLI
9
+
10
+ class << self
11
+
12
+ def error_msg(msg)
13
+ $stderr.puts "ERROR - #{msg}"
14
+ end
15
+
16
+ def fail(msg, code=1)
17
+ error_msg(msg)
18
+ exit code
19
+ end
20
+
21
+ def parse_config(path)
22
+ parsed = nil
23
+ open(path) do |stream|
24
+ parsed = YAML.load(stream)
25
+ end
26
+ if not parsed.respond_to?(:has_key?)
27
+ raise Exception.new("invalid YAML in #{path}; parsed #{parsed.inspect}")
28
+ end
29
+ puts "parsed config: #{parsed.inspect}"
30
+ required_keys = ['key', 'secret', 'token', 'token_secret']
31
+ missing_keys = []
32
+ vals = []
33
+ required_keys.each do |k|
34
+ v = parsed.fetch(k, nil)
35
+ if not v.nil?
36
+ vals << v
37
+ else
38
+ missing_keys << k
39
+ end
40
+ end
41
+ if not missing_keys.empty?
42
+ raise Exception.new("missing keys in #{path}: #{missing_keys.inspect}")
43
+ end
44
+ vals
45
+ end
46
+
47
+ def main
48
+ actions = {}
49
+
50
+ actions[:list_sets] = lambda do |client, args|
51
+ client.each_photoset do |pset|
52
+ puts Squarepusher.describe_photoset(pset)
53
+ end
54
+ end
55
+
56
+ actions[:grab_all_sets] = lambda do |client, args|
57
+ if args.size != 1
58
+ fail("expected: <output_dir>")
59
+ end
60
+
61
+ output_dir = args[0]
62
+
63
+ total_results = {}
64
+ client.each_photoset do |pset|
65
+ pset_description = Squarepusher.describe_photoset(pset)
66
+ puts "[set] #{pset_description}"
67
+ pset_results = client.download_photoset(pset, output_dir)
68
+ puts "[results] #{pset_description} #{pset_results.inspect}"
69
+ total_results[pset_description] = pset_results
70
+ puts
71
+ end
72
+
73
+ total_results.each_pair do |k, v|
74
+ puts "#{k}: #{v.inspect}"
75
+ end
76
+ end
77
+
78
+ actions[:grab_set] = lambda do |client, args|
79
+ if args.size != 2
80
+ fail("expected: <photoset_id> <output_dir>")
81
+ end
82
+
83
+ pset_id, output_dir = args
84
+ pset = client.get_photoset(pset_id)
85
+ results = client.download_photoset(pset, output_dir)
86
+ puts results.inspect
87
+ end
88
+
89
+ actions[:find_set] = lambda do |client, args|
90
+ if args.size != 1
91
+ fail("expected: <photoset_id>")
92
+ end
93
+
94
+ pset_id, output_dir = args
95
+ pset = client.get_photoset(pset_id)
96
+ puts Squarepusher.describe_photoset(pset)
97
+ end
98
+
99
+
100
+ def action_str(actions)
101
+ actions.keys.join(",")
102
+ end
103
+
104
+ def size_str
105
+ Squarepusher.sizes.join(",")
106
+ end
107
+
108
+ options = { :size => :original }
109
+ args = nil
110
+ action = nil
111
+ client = nil
112
+ config_path = "#{ENV['HOME']}/.squarepusher.yaml"
113
+ OptionParser.new do |opts|
114
+ opts.banner = "USAGE: squarepusher [options] <action:(#{action_str(actions)})> [args]"
115
+
116
+ opts.on("-c", "--config", "path to config file (defaults to #{config_path})") do |v|
117
+ options[:config] = v
118
+ end
119
+
120
+ opts.on("-o", "--overwrite", "overwrite already downloaded files") do |v|
121
+ options[:overwrite] = v
122
+ end
123
+
124
+ opts.on("-s", "--size SIZE", "size of photos to download (#{size_str()})") do |v|
125
+ options[:size] = v.to_sym
126
+ end
127
+
128
+ opts.on("-v", "--verbose", "log verbosely") do |v|
129
+ options[:verbose] = v
130
+ end
131
+
132
+ opts.parse!(ARGV)
133
+
134
+ if ARGV.size < 1
135
+ $stderr.puts opts
136
+ exit 1
137
+ end
138
+
139
+ action = ARGV.delete_at(0)
140
+ args = ARGV
141
+
142
+ action = action.to_sym
143
+ if not actions.has_key?(action)
144
+ $stderr.puts opts
145
+ exit 2
146
+ end
147
+
148
+ config_path = options[:config] || config_path
149
+ if not File.exists?(config_path)
150
+ fail "#{config_path} not found"
151
+ else
152
+ puts "parsing #{config_path}"
153
+ end
154
+
155
+ key, secret, token, token_secret = parse_config(config_path)
156
+ client = Squarepusher::Client.new(key, secret, token, token_secret, options)
157
+ end
158
+
159
+ puts "args: #{args.inspect}"
160
+ actions[action].call(client, args || [])
161
+ end
162
+
163
+ end
164
+
165
+ end
166
+
167
+ end
@@ -0,0 +1,214 @@
1
+ require 'fileutils'
2
+ require 'optparse'
3
+
4
+ FlickRawOptions = {}
5
+
6
+ $fileutils = FileUtils::Verbose
7
+
8
+ # TODO: detect "photo unavailable" and don't download image
9
+ UNAVAILABLE_URL = 'http://l.yimg.com/g/images/photo_unavailable.gif'
10
+
11
+ # TODO: keep track of failures
12
+
13
+ module Squarepusher
14
+
15
+ class << self
16
+
17
+ def describe_photoset(pset)
18
+ "#{pset.id} '#{pset.title}'"
19
+ end
20
+
21
+ def normalize(name)
22
+ name.gsub(/[^a-zA-Z0-9_+\.=-]+/, '-')
23
+ end
24
+
25
+ def sizes
26
+ return [:original, :large, :medium_640, :medium_500, :small, :thumb, :small_square]
27
+ end
28
+
29
+ end
30
+
31
+ class Client
32
+
33
+ def initialize(key, secret, token, token_secret, args={})
34
+ @overwrite = args[:overwrite] || false
35
+ @verbose = args[:verbose] || false
36
+
37
+ FlickRawOptions['timeout'] = args[:timeout] || 5
38
+
39
+ require 'flickraw'
40
+
41
+ FlickRaw.api_key = key
42
+ FlickRaw.shared_secret = secret
43
+
44
+ # flickr.auth.checkToken(:auth_token => token)
45
+ flickr.access_token = token
46
+ flickr.access_secret = token_secret
47
+
48
+ size = args[:size] || :small_square
49
+
50
+ @url_for_photo = case size
51
+ when :original
52
+ lambda { |p| FlickRaw.url_o(p) }
53
+ when :large
54
+ lambda { |p| FlickRaw.url_b(p) }
55
+ when :medium_640
56
+ lambda { |p| FlickRaw.url_z(p) }
57
+ when :medium_500
58
+ lambda { |p| FlickRaw.url(p) }
59
+ when :small
60
+ lambda { |p| FlickRaw.url_m(p) }
61
+ when :thumb
62
+ lambda { |p| FlickRaw.url_t(p) }
63
+ when :small_square
64
+ lambda { |p| FlickRaw.url_s(p) }
65
+ else
66
+ raise Exception("unrecognized size: #{size}")
67
+ end
68
+ end
69
+
70
+ def get_photoset(pset_id)
71
+ flickr.photosets.getInfo(:photoset_id => pset_id)
72
+ end
73
+
74
+ def each_photoset
75
+ flickr.photosets.getList.each do |pset|
76
+ yield pset
77
+ end
78
+ end
79
+
80
+ def download_photoset(photoset, output_dir)
81
+ dirname = Squarepusher.normalize(photoset.title)
82
+ set_dir = File.join(output_dir, dirname)
83
+ $fileutils.mkdir_p set_dir
84
+
85
+ # handles socket timeout when loading photoset info
86
+ results = {}
87
+ status, photoset_result = handle_error { flickr.photosets.getPhotos(:photoset_id => photoset.id, :extras => "original_format,url_o")["photo"] }
88
+ if status == :error
89
+ error photoset_result
90
+ results[status] = 1
91
+ return results
92
+ else
93
+ photos = photoset_result
94
+ end
95
+
96
+ photos.each do |p|
97
+ # TODO: use name of file in url since titles can be duplicate
98
+ # copies string?
99
+ name = "#{p.id}"
100
+ if not p.title.empty?
101
+ normalized_title = Squarepusher.normalize(p.title)
102
+ name << "-#{normalized_title}"
103
+ end
104
+
105
+ url = @url_for_photo[p]
106
+
107
+ # TODO: only add .jpg suffix if it's not in the image name already
108
+ path = File.join(set_dir, name)
109
+ path << ".jpg" if not path =~ /.jpg$/
110
+
111
+ if not @overwrite and File.exists?(path)
112
+ debug "#{path} exists; skipping"
113
+ result = :exists
114
+ else
115
+ result = download_image(url, path)
116
+ end
117
+
118
+ if results.has_key?(result)
119
+ results[result] = results[result] + 1
120
+ else
121
+ results[result] = 1
122
+ end
123
+ end
124
+ results
125
+ end
126
+
127
+ private
128
+
129
+ # was originally sending this to stderr, but the difference in flushing between
130
+ # stdout and stderr was creating logging confusion
131
+ def error(msg)
132
+ puts "ERROR: #{msg}"
133
+ end
134
+
135
+ def debug(msg)
136
+ puts msg if @verbose
137
+ end
138
+
139
+ def info(msg)
140
+ puts msg
141
+ end
142
+
143
+ def download_image(url, path, args={})
144
+ if url == UNAVAILABLE_URL
145
+ redirects = args[:redirects]
146
+ msg = "#{url} unavailable"
147
+ msg << "; redirects: #{redirects}" if not redirects.nil?
148
+ debug msg
149
+ return :unavailable
150
+ end
151
+
152
+ result = :unknown
153
+ uri = URI.parse(url)
154
+ begin
155
+ Net::HTTP.start(uri.host, uri.port) do |http|
156
+ full_path = uri.request_uri
157
+ response = http.get(full_path)
158
+
159
+ # puts response.inspect
160
+ case response
161
+ when Net::HTTPError
162
+ result = :error
163
+ when Net::HTTPFound
164
+ redirects = args[:redirects] || []
165
+ redirects << url
166
+ location = response["location"]
167
+ if not location =~ /^http.*/
168
+ location = "#{uri.scheme}://#{uri.host}:#{uri.port}#{location}"
169
+ end
170
+ result = download_image(location, path, :redirects => redirects)
171
+ else
172
+ debug "#{url} -> #{path}"
173
+ if @verbose
174
+ response.each_header do |k, v|
175
+ puts "#{k}: #{v}"
176
+ end
177
+ puts
178
+ end
179
+
180
+ # detects weird 404 or 504 responses included in body but not HTTP status
181
+ content_type = response["content-type"]
182
+ if not (content_type =~ /text\/\w+/).nil?
183
+ error "unexpected content type: #{content_type}"
184
+ result = :error
185
+ else
186
+ open(path, 'w') do |out|
187
+ out << response.body
188
+ end
189
+ result = :success
190
+ end
191
+ end
192
+ end
193
+ rescue Exception => e
194
+ error e
195
+ result = :error
196
+ end
197
+
198
+ return result
199
+ end
200
+
201
+ def handle_error
202
+ raise Exception("block required") if not block_given?
203
+ begin
204
+ block_result = yield
205
+ result = [:success, block_result]
206
+ rescue
207
+ result = [:error, $!]
208
+ end
209
+ return result
210
+ end
211
+
212
+ end
213
+
214
+ end
@@ -1,3 +1,3 @@
1
1
  module Squarepusher
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
data/lib/squarepusher.rb CHANGED
@@ -1,143 +1,210 @@
1
- require 'fileutils'
2
- require 'optparse'
1
+ require 'squarepusher/cli'
2
+ require 'squarepusher/core'
3
+ require 'squarepusher/version'
3
4
 
4
- FlickRawOptions = {}
5
-
6
- $fileutils = FileUtils::Verbose
7
-
8
- # TODO: detect "photo unavailable" and don't download image
9
- UNAVAILABLE_URL = 'http://l.yimg.com/g/images/photo_unavailable.gif'
10
-
11
- # TODO: keep track of failures
12
-
13
- module Squarepusher
14
-
15
- class << self
16
-
17
- def describe_photoset(pset)
18
- "#{pset.id} #{pset.title}"
19
- end
20
-
21
- end
22
-
23
- class Client
24
-
25
- def initialize(key, secret, token, args={})
26
- FlickRawOptions['timeout'] = args[:timeout] || 5
27
-
28
- require 'flickraw'
29
-
30
- FlickRaw.api_key = key
31
- FlickRaw.shared_secret = secret
32
-
33
- flickr.auth.checkToken(:auth_token => token)
34
-
35
- # FlickRaw.auth_token = token
36
- # FlickRaw.timeout = 5
37
-
38
- size = args[:size] || :large
39
-
40
- @url_for_photo = case size
41
- when :original
42
- lambda { |p| FlickRaw.url_o(p) }
43
- when :large
44
- lambda { |p| FlickRaw.url_b(p) }
45
- when :medium_640
46
- lambda { |p| FlickRaw.url_z(p) }
47
- when :medium_500
48
- lambda { |p| FlickRaw.url(p) }
49
- when :small
50
- lambda { |p| FlickRaw.url_m(p) }
51
- when :thumb
52
- lambda { |p| FlickRaw.url_t(p) }
53
- when :small_square
54
- lambda { |p| FlickRaw.url_s(p) }
55
- else
56
- raise Exception("unrecognized size: #{size}")
57
- end
58
- end
59
-
60
- def get_photoset(pset_id)
61
- flickr.photosets.getInfo(:photoset_id => pset_id)
62
- end
63
-
64
- def each_photoset
65
- flickr.photosets.getList.each do |pset|
66
- yield pset
67
- end
68
- end
69
-
70
- def download_photoset(photoset, output_dir)
71
- set_dir = File.join(output_dir, photoset.title.gsub(/\s+/, '-'))
72
- $fileutils.mkdir_p set_dir
73
-
74
- results = {}
75
- photos = flickr.photosets.getPhotos(:photoset_id => photoset.id, :extras => "original_format,url_o")["photo"]
76
- photos.each do |p|
77
- # puts p.inspect
78
- name = p.title.gsub(/[^\w_+\.-]/, '-')
79
-
80
- url = @url_for_photo[p]
81
-
82
- # TODO: only add .jpg suffix if it's not in the image name already
83
- path = File.join(set_dir, "#{name}")
84
- path << ".jpg" if not path =~ /.jpg$/
85
-
86
- if File.exists?(path)
87
- puts "#{path} exists; skipping"
88
- else
89
- result = download_image(url, path)
90
- if results.has_key?(result)
91
- results[result] = results[result] + 1
92
- else
93
- results[result] = 1
94
- end
95
- end
96
- end
97
- results
98
- end
99
-
100
- private
101
-
102
- def download_image(url, path, args={})
103
- if url == UNAVAILABLE_URL
104
- redirects = args[:redirects]
105
- msg = "#{url} unavailable"
106
- msg << "; redirects: #{redirects}" if not redirects.nil?
107
- puts msg
108
- return :unvailable
109
- end
110
-
111
- result = :unknown
112
- # puts url
113
- uri = URI.parse(url)
114
- Net::HTTP.start(uri.host, uri.port) do |http|
115
- full_path = uri.request_uri
116
- response = http.get(full_path)
117
-
118
- # puts response.inspect
119
- case response
120
- when Net::HTTPError
121
- result = :error
122
- when Net::HTTPFound
123
- redirects = args[:redirects] || []
124
- redirects << url
125
- location = response["location"]
126
- if not location =~ /^http.*/
127
- location = "#{uri.scheme}://#{uri.host}:#{uri.port}#{location}"
128
- end
129
- download_image(location, path, :redirects => redirects)
130
- else
131
- puts "#{url} -> #{path}"
132
- open(path, 'w') do |out|
133
- out << response.body
134
- end
135
- result = :success
136
- end
137
- end
138
- return result
139
- end
140
-
141
- end
142
-
143
- end
5
+ # require 'fileutils'
6
+ # require 'optparse'
7
+ #
8
+ # FlickRawOptions = {}
9
+ #
10
+ # $fileutils = FileUtils::Verbose
11
+ #
12
+ # # TODO: detect "photo unavailable" and don't download image
13
+ # UNAVAILABLE_URL = 'http://l.yimg.com/g/images/photo_unavailable.gif'
14
+ #
15
+ # # TODO: keep track of failures
16
+ #
17
+ # module Squarepusher
18
+ #
19
+ # class << self
20
+ #
21
+ # def describe_photoset(pset)
22
+ # "#{pset.id} '#{pset.title}'"
23
+ # end
24
+ #
25
+ # def normalize(name)
26
+ # name.gsub(/[^a-zA-Z0-9_+\.=-]+/, '-')
27
+ # end
28
+ #
29
+ # def sizes
30
+ # return [:original, :large, :medium_640, :medium_500, :small, :thumb, :small_square]
31
+ # end
32
+ #
33
+ # end
34
+ #
35
+ # class Client
36
+ #
37
+ # def initialize(key, secret, token, args={})
38
+ # @overwrite = args[:overwrite] || false
39
+ # @verbose = args[:verbose] || false
40
+ #
41
+ # FlickRawOptions['timeout'] = args[:timeout] || 5
42
+ #
43
+ # require 'flickraw'
44
+ #
45
+ # FlickRaw.api_key = key
46
+ # FlickRaw.shared_secret = secret
47
+ #
48
+ # flickr.auth.checkToken(:auth_token => token)
49
+ #
50
+ # size = args[:size] || :small_square
51
+ #
52
+ # @url_for_photo = case size
53
+ # when :original
54
+ # lambda { |p| FlickRaw.url_o(p) }
55
+ # when :large
56
+ # lambda { |p| FlickRaw.url_b(p) }
57
+ # when :medium_640
58
+ # lambda { |p| FlickRaw.url_z(p) }
59
+ # when :medium_500
60
+ # lambda { |p| FlickRaw.url(p) }
61
+ # when :small
62
+ # lambda { |p| FlickRaw.url_m(p) }
63
+ # when :thumb
64
+ # lambda { |p| FlickRaw.url_t(p) }
65
+ # when :small_square
66
+ # lambda { |p| FlickRaw.url_s(p) }
67
+ # else
68
+ # raise Exception("unrecognized size: #{size}")
69
+ # end
70
+ # end
71
+ #
72
+ # def get_photoset(pset_id)
73
+ # flickr.photosets.getInfo(:photoset_id => pset_id)
74
+ # end
75
+ #
76
+ # def each_photoset
77
+ # flickr.photosets.getList.each do |pset|
78
+ # yield pset
79
+ # end
80
+ # end
81
+ #
82
+ # def download_photoset(photoset, output_dir)
83
+ # dirname = Squarepusher.normalize(photoset.title)
84
+ # set_dir = File.join(output_dir, dirname)
85
+ # $fileutils.mkdir_p set_dir
86
+ #
87
+ # # handles socket timeout when loading photoset info
88
+ # results = {}
89
+ # status, photoset_result = handle_error { flickr.photosets.getPhotos(:photoset_id => photoset.id, :extras => "original_format,url_o")["photo"] }
90
+ # if status == :error
91
+ # error photoset_result
92
+ # results[status] = 1
93
+ # return results
94
+ # else
95
+ # photos = photoset_result
96
+ # end
97
+ #
98
+ # photos.each do |p|
99
+ # # puts p.inspect
100
+ #
101
+ # # TODO: use name of file in url since titles can be duplicate
102
+ # # copies string?
103
+ # name = "#{p.id}"
104
+ # if not p.title.empty?
105
+ # normalized_title = Squarepusher.normalize(p.title)
106
+ # name << "-#{normalized_title}"
107
+ # end
108
+ #
109
+ # url = @url_for_photo[p]
110
+ #
111
+ # # TODO: only add .jpg suffix if it's not in the image name already
112
+ # path = File.join(set_dir, name)
113
+ # path << ".jpg" if not path =~ /.jpg$/
114
+ #
115
+ # if not @overwrite and File.exists?(path)
116
+ # puts "#{path} exists; skipping"
117
+ # result = :exists
118
+ # else
119
+ # result = download_image(url, path)
120
+ # end
121
+ #
122
+ # if results.has_key?(result)
123
+ # results[result] = results[result] + 1
124
+ # else
125
+ # results[result] = 1
126
+ # end
127
+ # end
128
+ # results
129
+ # end
130
+ #
131
+ # private
132
+ #
133
+ # # was originally sending this to stderr, but the difference in flushing between
134
+ # # stdout and stderr was creating logging confusion
135
+ # def error(msg)
136
+ # puts "ERROR: #{msg}"
137
+ # end
138
+ #
139
+ # def download_image(url, path, args={})
140
+ # if url == UNAVAILABLE_URL
141
+ # redirects = args[:redirects]
142
+ # msg = "#{url} unavailable"
143
+ # msg << "; redirects: #{redirects}" if not redirects.nil?
144
+ # puts msg
145
+ # return :unavailable
146
+ # end
147
+ #
148
+ # result = :unknown
149
+ # uri = URI.parse(url)
150
+ # begin
151
+ # Net::HTTP.start(uri.host, uri.port) do |http|
152
+ # full_path = uri.request_uri
153
+ # response = http.get(full_path)
154
+ #
155
+ # # puts response.inspect
156
+ # case response
157
+ # when Net::HTTPError
158
+ # result = :error
159
+ # when Net::HTTPFound
160
+ # redirects = args[:redirects] || []
161
+ # redirects << url
162
+ # location = response["location"]
163
+ # if not location =~ /^http.*/
164
+ # location = "#{uri.scheme}://#{uri.host}:#{uri.port}#{location}"
165
+ # end
166
+ # result = download_image(location, path, :redirects => redirects)
167
+ # else
168
+ # puts "#{url} -> #{path}"
169
+ # if @verbose
170
+ # response.each_header do |k, v|
171
+ # puts "#{k}: #{v}"
172
+ # end
173
+ # puts
174
+ # end
175
+ #
176
+ # # detects weird 404 or 504 responses included in body but not HTTP status
177
+ # content_type = response["content-type"]
178
+ # if not (content_type =~ /text\/\w+/).nil?
179
+ # error "unexpected content type: #{content_type}"
180
+ # result = :error
181
+ # else
182
+ # open(path, 'w') do |out|
183
+ # out << response.body
184
+ # end
185
+ # result = :success
186
+ # end
187
+ # end
188
+ # end
189
+ # rescue Exception => e
190
+ # error e
191
+ # result = :error
192
+ # end
193
+ #
194
+ # return result
195
+ # end
196
+ #
197
+ # def handle_error
198
+ # raise Exception("block required") if not block_given?
199
+ # begin
200
+ # block_result = yield
201
+ # result = [:success, block_result]
202
+ # rescue
203
+ # result = [:error, $!]
204
+ # end
205
+ # return result
206
+ # end
207
+ #
208
+ # end
209
+ #
210
+ # end
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: squarepusher
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
5
- prerelease:
4
+ prerelease: false
6
5
  segments:
7
6
  - 0
8
7
  - 0
9
- - 3
10
- version: 0.0.3
8
+ - 4
9
+ version: 0.0.4
11
10
  platform: ruby
12
11
  authors:
13
12
  - mhawthorne
@@ -15,7 +14,7 @@ autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2011-03-03 00:00:00 -05:00
17
+ date: 2011-10-24 00:00:00 -07:00
19
18
  default_executable:
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency
@@ -26,7 +25,6 @@ dependencies:
26
25
  requirements:
27
26
  - - ">="
28
27
  - !ruby/object:Gem::Version
29
- hash: 3
30
28
  segments:
31
29
  - 0
32
30
  version: "0"
@@ -43,9 +41,12 @@ extra_rdoc_files: []
43
41
  files:
44
42
  - .gitignore
45
43
  - Gemfile
44
+ - README.md
46
45
  - Rakefile
47
46
  - bin/squarepusher
48
47
  - lib/squarepusher.rb
48
+ - lib/squarepusher/cli.rb
49
+ - lib/squarepusher/core.rb
49
50
  - lib/squarepusher/version.rb
50
51
  - squarepusher.gemspec
51
52
  has_rdoc: true
@@ -62,7 +63,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
62
63
  requirements:
63
64
  - - ">="
64
65
  - !ruby/object:Gem::Version
65
- hash: 3
66
66
  segments:
67
67
  - 0
68
68
  version: "0"
@@ -71,14 +71,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
71
71
  requirements:
72
72
  - - ">="
73
73
  - !ruby/object:Gem::Version
74
- hash: 3
75
74
  segments:
76
75
  - 0
77
76
  version: "0"
78
77
  requirements: []
79
78
 
80
79
  rubyforge_project: nowarning
81
- rubygems_version: 1.5.0
80
+ rubygems_version: 1.3.7
82
81
  signing_key:
83
82
  specification_version: 3
84
83
  summary: downloads photos from flickr