-
Notifications
You must be signed in to change notification settings - Fork 0
/
ompload
executable file
·252 lines (205 loc) · 6.68 KB
/
ompload
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
#!/usr/bin/env ruby
#
# Copyright 2007-2009 David Shakaryan <[email protected]>
# Copyright 2007-2009 Brenden Matthews <[email protected]>
# Copyright 2010 Murilo Soares Pereira <[email protected]>
#
# Distributed under the terms of the GNU General Public License v3
#
# Special thanks to Christoph for a patch.
# Thanks to Murilo for the major refactoring
#
#
# Added -H "Expect:" to curl options.. was screwing up my squid proxy with http/1.0 crap..
# ` Chris Hall [email protected] 3-24-11
#
#
require 'singleton'
require 'getoptlong'
require 'tempfile'
class XclipBuffer
include Singleton
attr_reader :content
def initialize
@content = ''
end
def append!(string)
@content += "#{string}\n"
end
end
class ErrorCounter
include Singleton
attr_reader :count
def initialize
@count = 0
end
def increment!
@count += 1
end
end
module Shell
def curl_installed?
!%x{curl --version 2> /dev/null}.empty?
end
def xclip_installed?
!%x{which xclip 2> /dev/null}.empty?
end
def piped_data_given?
!STDIN.tty?
end
end
module Omploader
URL = 'http://ompldr.org'
UPLOAD_URL = "#{URL}/upload"
extend self
def file_url(id)
"#{URL}/v#{id}"
end
end
module Ompload
MAX_FILE_SIZE = 2**32
USAGE = <<-USAGE.gsub(/^ /, '')
Usage: ompload [-h|--help] [options] [file(s)]
-q, --quiet Only output errors and warnings
-u, --url Only output URL when finished
-f, --filename Filename to use when posting data
from stdin
-n, --no-clip Disable copying of URL to clipboard
(this feature uses the xclip tool)
You can supply a list of files or data via stdin (or both)
This script requires a copy of cURL in the path,
and will automatically copy the list of URLs to.
the X11 clipboard if the `xclip' program is
available in your PATH.
USAGE
class ThrottledError < StandardError; end
module Message
extend self
def curl_failed_posting_file(file_path)
"error: curl failed to return a response uploading '#{file_path}'"
end
def throttled(file_path)
"error: got throttled when trying to ompload '#{file_path}'\n" <<
"Awaiting 60s and attempting to continue..."
end
def progress(file_path)
"Progress for '#{file_path}'"
end
def omploaded(file_path, id)
"#{Omploader.file_url(id)}"
end
def invalid_file(file_path)
"error: '#{file_path}' does not exist or is not a regular file"
end
def file_too_big(file_path)
"error: '#{file_path}' exceeds #{MAX_FILE_SIZE} bytes " <<
"(size is #{File.size(file_path)})."
end
end
module UploadsHandler
extend self, Shell
def handle_file(file_path, options = {})
puts Message.progress(file_path) if !options[:quiet] && !options[:url]
response = upload_with_curl({ :file_path => file_path,
:silent => options[:quiet] || options[:url] })
handle_response!(response, file_path, options)
rescue ThrottledError
STDERR.puts Message.throttled(file_path)
sleep(60) and retry
end
def handle_files(file_paths, options = {})
file_paths.each do |file_path|
if !File.file?(file_path)
STDERR.puts Message.invalid_file(file_path)
ErrorCounter.instance.increment!
elsif File.size(file_path) > MAX_FILE_SIZE
STDERR.puts Message.file_too_big(file_path)
ErrorCounter.instance.increment!
else
handle_file(file_path, options)
end
end
end
def handle_data(data, options = {})
file_name = options[:file_name] || 'piped data'
puts Message.progress(file_name) if !options[:quiet] && !options[:url]
response = upload_with_curl({ :data => data,
:file_name => file_name,
:silent => options[:quiet] || options[:url] })
handle_response!(response, file_name, options)
rescue ThrottledError
STDERR.puts Message.throttled(file_name)
sleep(60) and retry
end
private
def upload_with_curl(options)
response = Tempfile.new('ompload')
progress_bar_or_silent = options[:silent] ? '-s' : '-#'
if options[:data]
IO.popen("curl #{progress_bar_or_silent} -H 'Expect:' -F 'file1=@-;filename=#{options[:file_name]}' #{Omploader::UPLOAD_URL} -o '#{response.path}'", "w+") do |pipe|
pipe.puts options[:data]
end
elsif options[:file_path]
%x{curl #{progress_bar_or_silent} -H 'Expect:' -F file1=@#{options[:file_path].inspect} #{Omploader::UPLOAD_URL} -o '#{response.path}'}
end
IO.read(response.path)
end
def handle_response!(response, file_name, options)
if response =~ /Slow down there, cowboy\./
raise ThrottledError
else
if response =~ /View file: <a href="v([A-Za-z0-9+\/]+)">/
puts Message.omploaded(file_name, $1) unless options[:quiet]
if xclip_installed? && options[:clip]
XclipBuffer.instance.append!("#{Omploader.file_url($1)}")
end
else
STDERR.puts Message.curl_failed_posting_file(file_name)
ErrorCounter.instance.increment!
end
end
end
end
module CLI
extend self, Shell
def run(argv, options = {})
unless curl_installed?
abort('error: curl missing or not in path. Cannot continue.')
end
abort(USAGE) if ARGV.size < 1 && !piped_data_given? || options[:help]
UploadsHandler.handle_files(ARGV, options)
UploadsHandler.handle_data(STDIN.read(4096), options) if piped_data_given?
if xclip_installed? && options[:clip] && !XclipBuffer.instance.content.empty?
IO.popen('xclip', 'w+').puts XclipBuffer.instance.content
end
if !options[:quiet] && !options[:url]
if ErrorCounter.instance.count > 0
puts "Finished with #{ErrorCounter.instance.count} errors."
else
puts 'Success.'
end
end
end
end
end
opts = GetoptLong.new(['--help', '-h', GetoptLong::NO_ARGUMENT],
['--filename', '-f', GetoptLong::REQUIRED_ARGUMENT],
['--quiet', '-q', GetoptLong::NO_ARGUMENT],
['--url', '-u', GetoptLong::NO_ARGUMENT],
['--no-clip', '-n', GetoptLong::NO_ARGUMENT])
options = { :clip => true }
opts.each do |opt, arg|
case opt
when '--help'
options[:help] = true
when '--filename'
options[:file_name] = arg
when '--quiet'
options[:quiet] = true
when '--url'
options[:url] = true
when '--no-clip'
options[:clip] = false
end
end
Ompload::CLI.run(ARGV, options) if $0 == __FILE__