bropages 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +15 -0
  2. data/bin/bro +3 -0
  3. data/lib/bro.rb +323 -0
  4. metadata +116 -0
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NGUzZTk4OGZlNGJkNmI3NWQxM2IxMzdlNjA0YjI2MWViOTcyM2FjNA==
5
+ data.tar.gz: !binary |-
6
+ MmYwZjg2OTMzN2VjYmI2ZTQzYWUxMDY2NDRhMzA4NzkzNTJhZTIzZg==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NDAyNTJmMDFmMGQ1MzNkMGJhZTBmNzM1NDUzYTAyNDIzOGUyYzYxODg1Y2Jj
10
+ MmY3MDBhZWIyYjVhMDEwZjYwNjc5YTUzMDgwYWFmZTZkNzY0MzNmNDU0Mzhi
11
+ MTFkZWEzY2Q5ZjQwNDk2ZDhmNzdjYzliOTFjNWNhNmZmYzQ3MzI=
12
+ data.tar.gz: !binary |-
13
+ NThhNDc3N2M4NzRkNzY1ZDdiZmE2ZWU4OGQ4MWQ2MzVmMTIyOGZiZmE0ZmFl
14
+ NDA1YWUzMWM1ZDAyZTQ1NDVlMTBhZGRhZGJmMzkyZDUxNTdjYWVkNGVjOTI5
15
+ YjRlNzM5OTFhNDA4MzI2ODc4NDA1ZWYwNWQwOGExZmYzMTA5Nzk=
data/bin/bro ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bro'
data/lib/bro.rb ADDED
@@ -0,0 +1,323 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'json'
4
+ require 'commander/import'
5
+ require 'highline'
6
+ require 'smart_colored'
7
+ require 'rest-client'
8
+
9
+ URL = ENV["BROPAGES_URL"] || 'http://bropages.org'
10
+ FILE = ENV["HOME"] + '/.bro'
11
+
12
+ program :name, 'bro'
13
+ program :version, '0.0.3'
14
+ program :description, "Highly readable supplement to man pages.\n\nShows simple, concise examples for commands."
15
+
16
+ default_command :lookup
17
+
18
+ command :thanks do |c|
19
+ c.syntax = 'bro thanks [COMMAND]'
20
+ c.summary = 'Upvote an entry, bro'
21
+ c.description = 'Upvote a bro entry. If called without a COMMAND argument, it will upvote the last thing you looked up with bro'
22
+ c.example 'Upvote the bro entry for curl', 'bro thanks curl'
23
+ c.action do |args, options|
24
+ begin
25
+ login_details = check_email
26
+ rescue
27
+ say "Sorry, you can't do this without email verification".colored.red
28
+ end
29
+ unless login_details.nil?
30
+ cmd = read_state[:cmd]
31
+
32
+ if cmd.nil?
33
+ say "\nYou must first look up a command before downvoting. For example: bro curl\n\n"
34
+ return
35
+ end
36
+
37
+ idkey = args[0]
38
+ if idkey.nil?
39
+ idkey = "1"
40
+ end
41
+ id = read_state[idkey.intern]
42
+
43
+ if id.nil?
44
+ say "\nThat id (#{idkey}) does not exist for #{cmd}, try another one"
45
+ return
46
+ end
47
+
48
+ begin
49
+ res = RestClient.get URL + "/thanks/#{id}", { params: login_details }
50
+ rescue => e
51
+ say e.message
52
+ say "There was a problem thanking the #{cmd} entry. This entry may not exist or bropages.org may be down".colored.yellow.on_red
53
+ else
54
+ say "You just gave thanks for the top entry for #{cmd}!"
55
+ say res
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ command :no do |c|
62
+ c.syntax = 'bro no [ID]'
63
+ c.summary = 'Downvote an entry, bro'
64
+ c.description = 'Downvote a bro entry for the last command you looked up. If called without ID, it will downvote the top entry of the last command you looked up.'
65
+ c.example 'Downvote the bro entry for curl', "bro curl\n\nbro no"
66
+ c.action do |args, options|
67
+ begin
68
+ login_details = check_email
69
+ rescue
70
+ say "Sorry, you can't do this without email verification".colored.red
71
+ end
72
+ unless login_details.nil?
73
+
74
+ cmd = read_state[:cmd]
75
+
76
+ if cmd.nil?
77
+ say "\nYou must first look up a command before downvoting. For example: bro curl\n\n"
78
+ return
79
+ end
80
+
81
+ idkey = args[0]
82
+ if idkey.nil?
83
+ idkey = "1"
84
+ end
85
+ id = read_state[idkey.intern]
86
+
87
+ if id.nil?
88
+ say "\nThat id (#{idkey}) does not exist for #{cmd}, try another one"
89
+ return
90
+ end
91
+
92
+ begin
93
+ res = RestClient.get URL + "/no/#{id}", { params: login_details }
94
+ rescue => e
95
+ say e.message
96
+ say "There was a problem downvoting the #{cmd} entry. This entry may not exist or bropages.org may be down".colored.yellow.on_red
97
+ else
98
+ say "You just downvoted an entry for #{cmd}"
99
+ say res
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ command :add do |c|
106
+ c.syntax = 'bro add [COMMAND] [-m MESSAGE]'
107
+ c.summary = 'Add an entry, bro'
108
+ c.description = "This adds an entry to the http://bropages.org database.\n\nCalled without parameters will add an entry for the last thing you looked up with bro."
109
+ c.example 'Launch your editor to add an entry for curl', 'bro add curl'
110
+ c.example 'Quickly add an entry for curl', 'bro add curl -m "curl http://google.com"'
111
+ #TODO c.option '-m', 'An optional inline entry. This won\'t trigger a system editor to open'
112
+ c.action do |args, options|
113
+ begin
114
+ login_details = check_email
115
+ rescue
116
+ say "Sorry, you can't do this without email verification".colored.red
117
+ end
118
+
119
+ unless login_details.nil?
120
+
121
+ cmd = get_arg_or_last_command args
122
+
123
+ if cmd.nil?
124
+ say "\nYou must enter a COMMAND after 'bro add'. For example: bro add curl\n\n"
125
+ else
126
+ prompt = "#~ Bro entry for command '#{cmd}'\n#~ Just provide a few, simple, common case examples for how to use this command\n#~ Comments starting with #~ are removed\n"
127
+ entry = ask_editor prompt, "vim"
128
+ if entry.gsub(prompt, '').strip.length > 0
129
+ if agree "Submit this entry for #{cmd}? [Yn] "
130
+ say "All right, sending your entry..."
131
+ begin
132
+ res = RestClient.post URL + '/', login_details.merge({ entry: { cmd: cmd, msg: entry}, format: 'json', multipart: true })
133
+ rescue => e
134
+ say e.message
135
+ file = "/tmp/#{cmd}.bro"
136
+
137
+ # increment file name as to not overwrite anything
138
+ i = 1
139
+ while File.exist?(file)
140
+ file = "/tmp/#{cmd}#{i}.bro"
141
+ i += 1
142
+ end
143
+
144
+ # write message to file
145
+ File.open(file, 'w') do |f|
146
+ f.write entry
147
+ end
148
+ say "Woops. There was an error! Your entry was saved to #{file}".colored.yellow.on_red
149
+ else
150
+ say "Successfully submitted.".colored.green
151
+ end
152
+ end
153
+ else
154
+ say "Canceled. Did not submit entry for '#{cmd}'".colored.yellow.on_red
155
+ end
156
+ end
157
+ end
158
+ end
159
+ end
160
+
161
+ command :lookup do |c|
162
+ c.syntax = 'bro [COMMAND]'
163
+ c.summary = 'Lookup an entry, bro. Or just call bro [COMMAND]'
164
+ c.description = "This looks up entries in the http://bropages.org database."
165
+ c.example 'Look up the bro entries for curl', 'bro curl'
166
+ c.action do |args, options|
167
+ if args.empty?
168
+ say "\n#{"Bro! Specify a command first!".colored.red}\n\nFor example, try #{"bro curl".colored.green}\n\nUse #{"bro help".colored.yellow} for more info\n\n"
169
+ else
170
+ cmd = args.first
171
+
172
+ # write to ~/.bro file with last command
173
+ write_state({ cmd: cmd })
174
+
175
+ # connect to webservice for entry
176
+ error = false
177
+ begin
178
+ res = RestClient.get URL + '/' + cmd + '.json'
179
+ rescue => e
180
+ say "\nThe #{cmd.colored.yellow} command isn't in our database\n\n\t* Use #{"bro add".colored.green.underline} to add #{cmd.colored.yellow} to our database!\n\n\t* Need help? Visit #{"http://bropages.org/help".colored.underline}\n\n"
181
+ error = true
182
+ end
183
+
184
+ unless error
185
+ enable_paging
186
+ list = JSON.parse res
187
+ s = list.length == 1 ? 'y' : 'ies'
188
+ say "#{list.length} entr#{s} for #{cmd}\n".colored.yellow.bold.underline
189
+
190
+ sep = ""
191
+ (HighLine::SystemExtensions.terminal_size[0] - 5).times { sep += "." }
192
+ sep += "\n"
193
+
194
+ i = 0
195
+ isDefault = true
196
+ list.each {|data|
197
+ i += 1
198
+
199
+ obj = {}
200
+ obj["#{i}"] = data['id']
201
+ write_state(obj)
202
+
203
+ days = (DateTime.now - DateTime.parse(data['updated_at'])).ceil.to_i
204
+
205
+ body = data['msg']
206
+
207
+ body = body.gsub(/^([^#][^\n]*)$/, "\\1".colored.magenta)
208
+
209
+ say sep + "\n\n" if i > 1
210
+
211
+ say body + "\n\n"
212
+
213
+ upstr = "bro thanks"
214
+ upstr += " #{i}" unless isDefault
215
+ downstr = "bro no"
216
+ downstr += " #{i}" unless isDefault
217
+ downstr += "\t" if isDefault
218
+
219
+ msg = "\t#{upstr.colored.green}\tto upvote (#{data['up']})\n\t#{downstr.colored.red}\tto downvote (#{data['down']})\n"
220
+ if days > 0
221
+ #msg += "\tlast updated\t#{days} days ago"
222
+ end
223
+ say msg + "\n\n"
224
+ isDefault = false
225
+ }
226
+ end
227
+ end
228
+ end
229
+ end
230
+
231
+ def get_arg_or_last_command args
232
+ cmd = args.first
233
+ if args.empty?
234
+ state = read_state
235
+ cmd = state[:cmd]
236
+ end
237
+ cmd
238
+ end
239
+
240
+ def check_email
241
+ begin
242
+ is_invalid_code read_state[:code], read_state[:email]
243
+ rescue => e
244
+ prompt_email
245
+ end
246
+ {code: read_state[:code], email: read_state[:email]}
247
+ end
248
+
249
+ def prompt_email
250
+ say "Bropages.org requires an email address verification to do this action".colored.yellow
251
+ say "Your email address and verification code will be saved locally on your machine to a file called #{"~/.bro".colored.yellow} and used for future bropages.org activity"
252
+ say "When you enter your email, you'll get a verification email with a code. Enter the code when prompted"
253
+
254
+ email = ""
255
+
256
+ while is_invalid_email email
257
+ email = ask "What's your email address?".colored.green
258
+ end
259
+
260
+ begin
261
+ res = RestClient.post URL + '/users.json', { user: { email: email }, format: 'json', multipart: true }
262
+ rescue => e
263
+ say "There was an error delivering to your email address. Please try again later".colored.yellow.on_red
264
+ raise e
265
+ else
266
+ say "Great! We're sending an email to #{email}. Enter the verification code below and you'll be all set from now on."
267
+
268
+ invalid_code = true
269
+ begin
270
+ code = ask "Please enter the verification code: "
271
+ begin
272
+ is_invalid_code code, email
273
+ invalid_code = false
274
+ say "Great! You're verified! FYI, your email and code are stored locally in ~/.bro"
275
+ write_state({ email: email, code: code })
276
+ rescue => e
277
+ say "Woops, there was a problem verifying your email. Please try again".colored.yellow.on_red
278
+ end
279
+ end while invalid_code
280
+ end
281
+
282
+ end
283
+
284
+ def is_invalid_code code, email
285
+ res = RestClient.get URL + "/users/verify?code=#{code}&email=#{email}"
286
+ end
287
+
288
+ def is_invalid_email email
289
+ regex = /^[a-zA-Z0-9_.+\-]+@[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-.]+$/
290
+ email.scan(regex).empty?
291
+ end
292
+
293
+ # write state to this file, using the existing key/vals as defaults
294
+ # format is key=val;key2=val;key3=val
295
+ def write_state obj
296
+ # read the ~/.bro file and load the settings as defaults
297
+ # we don't want to lose data if we're not writing over it all
298
+ read_state.each {|k,v|
299
+ obj[k] = v if obj[k].nil?
300
+ }
301
+
302
+ # actually serialize the data and write the file
303
+ File.open(FILE, 'w') do |file|
304
+ data_pairs = obj.collect{ |k,v| "#{k}=#{v}" }
305
+ file.write data_pairs.join(";") + "\n"
306
+ end
307
+ end
308
+
309
+ # read the ~/.bro file and return a hash of the values
310
+ def read_state
311
+ obj = {}
312
+ begin
313
+ contents = File.read FILE
314
+ contents.strip.split(";").each {|kv|
315
+ chunk = kv.split("=")
316
+ key = chunk[0].intern
317
+ obj[key] = chunk[1]
318
+ }
319
+ rescue => e
320
+ # ignore file not found
321
+ end
322
+ obj
323
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bropages
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - bropages.org
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-12-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: json
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: commander
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rest-client
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: smart_colored
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: highline
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Highly readable supplement to man pages. Shows simple, concise examples
84
+ for unix commands.
85
+ email: info@bropages.org
86
+ executables:
87
+ - bro
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - bin/bro
92
+ - lib/bro.rb
93
+ homepage: http://bropages.org
94
+ licenses: []
95
+ metadata: {}
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ! '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubyforge_project:
112
+ rubygems_version: 2.2.1
113
+ signing_key:
114
+ specification_version: 4
115
+ summary: Bro
116
+ test_files: []