quickpress 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.
- checksums.yaml +7 -0
- data/.gitignore +24 -0
- data/Gemfile +4 -0
- data/LICENSE +674 -0
- data/README.md +163 -0
- data/Rakefile +3 -0
- data/bin/qp +417 -0
- data/lib/quickpress.rb +604 -0
- data/lib/quickpress/cli.rb +111 -0
- data/lib/quickpress/options.rb +21 -0
- data/lib/quickpress/version.rb +6 -0
- data/lib/quickpress/wordpress.rb +114 -0
- data/quickpress.gemspec +36 -0
- metadata +147 -0
data/lib/quickpress.rb
ADDED
@@ -0,0 +1,604 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'yaml'
|
3
|
+
require 'open-uri'
|
4
|
+
require 'tilt'
|
5
|
+
require 'quickpress/version'
|
6
|
+
require 'quickpress/wordpress'
|
7
|
+
require 'quickpress/cli'
|
8
|
+
require 'quickpress/options'
|
9
|
+
|
10
|
+
class String
|
11
|
+
# Removes starting whitespace.
|
12
|
+
def remove_starting
|
13
|
+
dup.remove_starting!
|
14
|
+
end
|
15
|
+
|
16
|
+
# Removes starting whitespace (destructive).
|
17
|
+
def remove_starting!
|
18
|
+
self.gsub(/^ +/, "")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Controls all operations we can make.
|
23
|
+
#
|
24
|
+
# This module's a mess.
|
25
|
+
#
|
26
|
+
# The code sucks, things are not splitted well...
|
27
|
+
# There should be delegation up the ass but I couldn't stop
|
28
|
+
# coding.
|
29
|
+
#
|
30
|
+
# Gotta study ruby guidelines and see other librarys' codes
|
31
|
+
# to see where I can improve.
|
32
|
+
#
|
33
|
+
module Quickpress
|
34
|
+
|
35
|
+
# Main directory where we store everything.
|
36
|
+
ROOT_DIR = File.expand_path "~/.config/quickpress"
|
37
|
+
CONFIG_FILE = "#{ROOT_DIR}/config.yml"
|
38
|
+
|
39
|
+
@@inited = nil
|
40
|
+
@@ran_first_time = false
|
41
|
+
|
42
|
+
# URL of the default site used to post.
|
43
|
+
@@default_site = nil
|
44
|
+
|
45
|
+
# Nice name of the default site.
|
46
|
+
@@default_sitename = nil
|
47
|
+
|
48
|
+
@@username = nil
|
49
|
+
@@password = nil
|
50
|
+
@@connection = nil
|
51
|
+
|
52
|
+
# Supported templating languages and their file extensions.
|
53
|
+
@@supported_markup = [["markdown" , '.md'],
|
54
|
+
["asciidoc" , '.adoc'],
|
55
|
+
["erb" , '.erb'],
|
56
|
+
["string" , '.str'],
|
57
|
+
["erubis" , '.erubis'],
|
58
|
+
["haml" , '.haml'],
|
59
|
+
["sass" , '.sass'],
|
60
|
+
["scss" , '.scss'],
|
61
|
+
["less" , '.less'],
|
62
|
+
["builder" , '.builder'],
|
63
|
+
["liquid" , '.liquid'],
|
64
|
+
["markdown" , '.md'],
|
65
|
+
["textile" , '.textile'],
|
66
|
+
["rdoc" , '.rdoc'],
|
67
|
+
["radius" , '.radius'],
|
68
|
+
["markaby" , '.mab'],
|
69
|
+
["nokogiri" , '.nokogiri'],
|
70
|
+
["coffeescript" , '.coffee'],
|
71
|
+
["creole" , '.creole'],
|
72
|
+
["mediawiki" , '.mw'],
|
73
|
+
["yajl" , '.yajl'],
|
74
|
+
["csv" , '.rcsv']]
|
75
|
+
|
76
|
+
module_function
|
77
|
+
|
78
|
+
# Loads default site from configuration file
|
79
|
+
def config_init
|
80
|
+
|
81
|
+
# Reading config file if exists
|
82
|
+
if File.exists? CONFIG_FILE
|
83
|
+
CLI::with_status("Initializing...") do
|
84
|
+
|
85
|
+
raw = File.read CONFIG_FILE
|
86
|
+
settings = YAML.load raw
|
87
|
+
settings = {} if not settings
|
88
|
+
|
89
|
+
@@default_site = settings["default_site"]
|
90
|
+
@@default_sitename = @@default_site.gsub(/htt(p|ps):\/\//, "").gsub(/\//, '-')
|
91
|
+
end
|
92
|
+
@@inited = true
|
93
|
+
end
|
94
|
+
|
95
|
+
FileUtils.mkdir_p ROOT_DIR if not File.exists? ROOT_DIR
|
96
|
+
end
|
97
|
+
|
98
|
+
# Executes at the first time, when there's no configuration
|
99
|
+
# directories.
|
100
|
+
#
|
101
|
+
# Asks stuff.
|
102
|
+
#
|
103
|
+
def first_time
|
104
|
+
puts <<-END.remove_starting!
|
105
|
+
Hello!
|
106
|
+
It looks like this is the first time you're
|
107
|
+
running quickpress.
|
108
|
+
|
109
|
+
Let's connect to your Wordpress(.com/.org) site.
|
110
|
+
END
|
111
|
+
puts
|
112
|
+
|
113
|
+
Quickpress::new_site(nil)
|
114
|
+
@@ran_first_time = true
|
115
|
+
end
|
116
|
+
|
117
|
+
# Adds site with URL `addr` to quickpress.
|
118
|
+
# If it's `nil`, will prompt the user for it.
|
119
|
+
def new_site(addr=nil)
|
120
|
+
return if @@ran_first_time
|
121
|
+
address = nil
|
122
|
+
|
123
|
+
# If retrying, go back here.
|
124
|
+
begin
|
125
|
+
address = addr.dup if not addr.nil? # cannot .dup NilClass
|
126
|
+
address ||= CLI::get("Address:")
|
127
|
+
|
128
|
+
address.gsub!(/http:\/\//, "")
|
129
|
+
address.gsub!(/www\./, "")
|
130
|
+
address.gsub!(/\/$/, "")
|
131
|
+
|
132
|
+
# Checking if site already exists
|
133
|
+
if File.exists? CONFIG_FILE
|
134
|
+
raw = File.read CONFIG_FILE
|
135
|
+
|
136
|
+
settings = {}
|
137
|
+
settings.merge!(YAML.load(raw))
|
138
|
+
|
139
|
+
settings["sites"].each do |s|
|
140
|
+
if address == s
|
141
|
+
puts
|
142
|
+
puts "There's already a site with address '#{address}'"
|
143
|
+
puts "Check it with `qp list-sites`."
|
144
|
+
|
145
|
+
if @@default_site == s
|
146
|
+
puts
|
147
|
+
puts "It's your default site, by the way"
|
148
|
+
end
|
149
|
+
exit 666
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
Quickpress::authenticate
|
155
|
+
|
156
|
+
# Will try to connect here.
|
157
|
+
# Might take a while.
|
158
|
+
CLI::with_status("Connecting...") do
|
159
|
+
@@connection = Wordpress.new(address, @@username, @@password)
|
160
|
+
end
|
161
|
+
|
162
|
+
puts <<-END.remove_starting!
|
163
|
+
|
164
|
+
Title: #{@@connection.title}
|
165
|
+
Tagline: #{@@connection.tagline}
|
166
|
+
Url: #{@@connection.url}
|
167
|
+
END
|
168
|
+
|
169
|
+
answer = CLI::ask "Is that right?"
|
170
|
+
fail "will retry" if not answer
|
171
|
+
|
172
|
+
# Last site added becomes the default
|
173
|
+
@@default_site = address
|
174
|
+
|
175
|
+
# Hey, this is our first site!
|
176
|
+
if not File.exists? CONFIG_FILE
|
177
|
+
|
178
|
+
# For a @@default_site like "http://myblog.com/this/dir"
|
179
|
+
#
|
180
|
+
# The @@default_sitename must be "myblog.com-this-dir"
|
181
|
+
@@default_sitename = address.gsub(/htt(p|ps):\/\//, "").gsub(/\//, '-')
|
182
|
+
|
183
|
+
# Saving to config file
|
184
|
+
settings = {}
|
185
|
+
|
186
|
+
settings["sites"] ||= []
|
187
|
+
settings["sites"] << @@default_site
|
188
|
+
|
189
|
+
settings["default_site"] = @@default_site
|
190
|
+
|
191
|
+
File.write(CONFIG_FILE, YAML.dump(settings))
|
192
|
+
|
193
|
+
# Config file exists
|
194
|
+
else
|
195
|
+
|
196
|
+
raw = File.read CONFIG_FILE
|
197
|
+
|
198
|
+
settings = {}
|
199
|
+
settings.merge!(YAML.load(raw))
|
200
|
+
|
201
|
+
settings["sites"] ||= []
|
202
|
+
settings["sites"] << @@default_site
|
203
|
+
|
204
|
+
settings["default_site"] = @@default_site
|
205
|
+
|
206
|
+
File.write(CONFIG_FILE, YAML.dump(settings))
|
207
|
+
end
|
208
|
+
|
209
|
+
rescue StandardError => e
|
210
|
+
retry if e.message =~ /will retry/
|
211
|
+
|
212
|
+
raise e
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
# Shows all saved sites.
|
217
|
+
def list_sites
|
218
|
+
|
219
|
+
# Hey, this is our first site!
|
220
|
+
if not File.exists? CONFIG_FILE
|
221
|
+
puts "No sites stored yet!"
|
222
|
+
puts
|
223
|
+
puts "Run `qp new-site` to create your first!"
|
224
|
+
|
225
|
+
else
|
226
|
+
raw = File.read CONFIG_FILE
|
227
|
+
|
228
|
+
settings = {}
|
229
|
+
settings.merge!(YAML.load(raw))
|
230
|
+
|
231
|
+
puts "Sites currently managed by quickpress:"
|
232
|
+
puts
|
233
|
+
|
234
|
+
settings["sites"].each_with_index do |site, i|
|
235
|
+
|
236
|
+
if @@default_site == site
|
237
|
+
puts (" %3d. %s <== default site" % [i, site])
|
238
|
+
else
|
239
|
+
puts (" %3d. %s" % [i, site])
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
end
|
245
|
+
|
246
|
+
def forget_site ids
|
247
|
+
|
248
|
+
# Hey, there's no sites added yet!
|
249
|
+
if not File.exists? CONFIG_FILE
|
250
|
+
puts "No sites managed with quickpress yet!"
|
251
|
+
puts "Add them with `qp new-site`"
|
252
|
+
exit 666
|
253
|
+
end
|
254
|
+
|
255
|
+
# Getting all sites from config file
|
256
|
+
raw = File.read CONFIG_FILE
|
257
|
+
|
258
|
+
settings = {}
|
259
|
+
settings.merge!(YAML.load(raw))
|
260
|
+
|
261
|
+
max_id = settings["sites"].size - 1
|
262
|
+
ids_to_delete = []
|
263
|
+
|
264
|
+
# Here we go!
|
265
|
+
ids.split(',').each do |id|
|
266
|
+
|
267
|
+
if not (0..max_id).include? id.to_i
|
268
|
+
puts "Invalid id!"
|
269
|
+
puts "Must be between 0 and #{max_id}."
|
270
|
+
next
|
271
|
+
end
|
272
|
+
|
273
|
+
puts "Will delete the following site:"
|
274
|
+
puts
|
275
|
+
puts settings["sites"][id.to_i]
|
276
|
+
|
277
|
+
if not $options[:force]
|
278
|
+
answer = CLI::ask("Is that right?")
|
279
|
+
if not answer
|
280
|
+
puts "Alright, then!"
|
281
|
+
next
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
ids_to_delete << id.to_i
|
286
|
+
end
|
287
|
+
|
288
|
+
# Forgetting a lot of sites at once
|
289
|
+
# Note: Is there a better way to do this?
|
290
|
+
# Once I delete an id, all the others change!
|
291
|
+
# I can't simply `each do delete` them.
|
292
|
+
|
293
|
+
ids_to_delete.each {|i| settings["sites"][i] = "will_delete" }
|
294
|
+
|
295
|
+
settings["sites"].reject! { |s| s == "will_delete" }
|
296
|
+
|
297
|
+
# Just in case we've just deleted the default site,
|
298
|
+
# let's grab the first one left
|
299
|
+
if not settings["sites"].include? @@default_site
|
300
|
+
if not settings["sites"].empty?
|
301
|
+
settings["default_site"] = settings["sites"].first
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
File.write(CONFIG_FILE, YAML.dump(settings))
|
306
|
+
|
307
|
+
# Ooh, boy
|
308
|
+
# We've just ran out of sites! Better delete that config file!
|
309
|
+
if settings["sites"].empty?
|
310
|
+
FileUtils.rm_f CONFIG_FILE
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
def use_site id
|
315
|
+
Quickpress::first_time if @@default_site.nil?
|
316
|
+
return if @@ran_first_time
|
317
|
+
|
318
|
+
# Hey, there's no sites added yet!
|
319
|
+
if not File.exists? CONFIG_FILE
|
320
|
+
puts "No sites managed with quickpress yet!"
|
321
|
+
puts ""
|
322
|
+
exit 666
|
323
|
+
end
|
324
|
+
|
325
|
+
# Getting all sites from config file
|
326
|
+
raw = File.read CONFIG_FILE
|
327
|
+
|
328
|
+
settings = {}
|
329
|
+
settings.merge!(YAML.load(raw))
|
330
|
+
|
331
|
+
max_id = settings["sites"].size - 1
|
332
|
+
|
333
|
+
if not (0..max_id).include? id.to_i
|
334
|
+
puts "Invalid id!"
|
335
|
+
puts "Must be between 0 and #{max_id}."
|
336
|
+
exit 666
|
337
|
+
end
|
338
|
+
|
339
|
+
site = settings["sites"][id]
|
340
|
+
|
341
|
+
puts "Default site: #{site}"
|
342
|
+
settings["default_site"] = site
|
343
|
+
File.write(CONFIG_FILE, YAML.dump(settings))
|
344
|
+
end
|
345
|
+
|
346
|
+
# Entrance for when we're creating a page or a post
|
347
|
+
# (`what` says so).
|
348
|
+
#
|
349
|
+
def new(what, filename=nil)
|
350
|
+
if filename.nil?
|
351
|
+
|
352
|
+
# Get editor to open temporary file
|
353
|
+
editor = ENV["EDITOR"]
|
354
|
+
if editor.nil?
|
355
|
+
editor = get("Which text editor we'll use?")
|
356
|
+
end
|
357
|
+
|
358
|
+
extension = nil
|
359
|
+
|
360
|
+
# No markup passed as argument
|
361
|
+
if $options[:markup].nil?
|
362
|
+
puts "Choose your templating language."
|
363
|
+
puts
|
364
|
+
|
365
|
+
@@supported_markup.each_with_index do |m, i|
|
366
|
+
puts (" %2d. %s (%s)" % [i, m[0], m[1]])
|
367
|
+
end
|
368
|
+
puts
|
369
|
+
|
370
|
+
id = CLI::get("Which one?").to_i
|
371
|
+
|
372
|
+
max_id = @@supported_markup.size - 1
|
373
|
+
|
374
|
+
if not (0..max_id).include? id
|
375
|
+
puts "Invalid id!"
|
376
|
+
puts "Must be between 0 and #{max_id}."
|
377
|
+
exit 666
|
378
|
+
end
|
379
|
+
|
380
|
+
extension = @@supported_markup[id][1]
|
381
|
+
|
382
|
+
# User specified filename to post
|
383
|
+
else
|
384
|
+
markup_id = nil
|
385
|
+
@@supported_markup.each_with_index do |m, i|
|
386
|
+
|
387
|
+
if m[0].casecmp($options[:markup]).zero?
|
388
|
+
markup_id = i
|
389
|
+
break
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
if markup_id.nil?
|
394
|
+
fail "Unknown markup laguage '#{$options[:markup]}'"
|
395
|
+
end
|
396
|
+
|
397
|
+
extension = @@supported_markup[markup_id][1]
|
398
|
+
end
|
399
|
+
|
400
|
+
# Create draft file
|
401
|
+
tempfile = Tempfile.new ['quickpress', extension]
|
402
|
+
tempfile.write "# Leave this file empty to cancel"
|
403
|
+
tempfile.flush
|
404
|
+
|
405
|
+
# Oh yeah, baby
|
406
|
+
`#{editor} #{tempfile.path}`
|
407
|
+
|
408
|
+
if tempfile.size.zero?
|
409
|
+
puts "Empty file: did nothing"
|
410
|
+
tempfile.close
|
411
|
+
exit 666
|
412
|
+
end
|
413
|
+
|
414
|
+
puts "File: '#{tempfile.path}'" if $options[:debug]
|
415
|
+
|
416
|
+
new_file(what, tempfile.path)
|
417
|
+
tempfile.close
|
418
|
+
|
419
|
+
else
|
420
|
+
# Post file and copy it to posted directory.
|
421
|
+
new_file(what, filename)
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
# Actually sends post/page `filename` to the blog.
|
426
|
+
def new_file(what, filename)
|
427
|
+
Quickpress::startup
|
428
|
+
html = Tilt.new(filename).render
|
429
|
+
|
430
|
+
# If successful, will store page id and link
|
431
|
+
id, link = nil, nil
|
432
|
+
|
433
|
+
if what == :post
|
434
|
+
title = CLI::get "Post title:"
|
435
|
+
|
436
|
+
puts "Existing blog categories:"
|
437
|
+
@@connection.categories.each { |c| puts "* #{c}" }
|
438
|
+
|
439
|
+
puts "Use a comma-separated list (eg. 'cat1, cat2, cat3')"
|
440
|
+
puts "Tab-completion works."
|
441
|
+
puts "(will create non-existing categories automatically)"
|
442
|
+
|
443
|
+
categories = CLI::tab_complete("Post categories:", @@connection.categories)
|
444
|
+
|
445
|
+
cats = []
|
446
|
+
categories.split(',').each { |c| cats << c.lstrip.strip }
|
447
|
+
|
448
|
+
CLI::with_status("Posting...") do
|
449
|
+
|
450
|
+
id, link = @@connection.post(:post_status => 'publish',
|
451
|
+
:post_date => Time.now,
|
452
|
+
:post_title => title,
|
453
|
+
:post_content => html,
|
454
|
+
:terms_names => {
|
455
|
+
:category => cats
|
456
|
+
})
|
457
|
+
end
|
458
|
+
puts "Post successful!"
|
459
|
+
|
460
|
+
elsif what == :page
|
461
|
+
title = CLI::get "Page title:"
|
462
|
+
|
463
|
+
CLI::with_status("Creating page...") do
|
464
|
+
|
465
|
+
id, link = @@connection.post(:post_status => 'publish',
|
466
|
+
:post_date => Time.now,
|
467
|
+
:post_title => title,
|
468
|
+
:post_content => html,
|
469
|
+
:post_type => 'page')
|
470
|
+
end
|
471
|
+
puts "Page created!"
|
472
|
+
end
|
473
|
+
|
474
|
+
puts <<-END.remove_starting!
|
475
|
+
id: #{id}
|
476
|
+
link: #{link}
|
477
|
+
END
|
478
|
+
end
|
479
|
+
|
480
|
+
# Deletes comma-separated list of posts/pages with `ids`.
|
481
|
+
# A single number is ok too.
|
482
|
+
def delete(what, ids)
|
483
|
+
Quickpress::startup
|
484
|
+
|
485
|
+
ids.split(',').each do |id|
|
486
|
+
|
487
|
+
thing = nil
|
488
|
+
|
489
|
+
CLI::with_status("Hold on a sec...") do
|
490
|
+
|
491
|
+
if what == :post
|
492
|
+
thing = @@connection.get_post id.to_i
|
493
|
+
elsif what == :page
|
494
|
+
thing = @@connection.get_page id.to_i
|
495
|
+
end
|
496
|
+
|
497
|
+
end
|
498
|
+
|
499
|
+
if what == :post
|
500
|
+
puts "Will delete the following post:"
|
501
|
+
elsif what == :page
|
502
|
+
puts "Will delete the following page:"
|
503
|
+
end
|
504
|
+
|
505
|
+
puts <<-END.remove_starting!
|
506
|
+
|
507
|
+
ID: #{thing["post_id"]}
|
508
|
+
Title: #{thing["post_title"]}
|
509
|
+
Date: #{thing["post_date"].to_time}
|
510
|
+
Status: #{thing["post_status"]}
|
511
|
+
URL: #{thing["link"]}
|
512
|
+
|
513
|
+
END
|
514
|
+
|
515
|
+
if not $options[:force]
|
516
|
+
answer = CLI::ask("Is that right?")
|
517
|
+
if not answer
|
518
|
+
puts "Alright, then!"
|
519
|
+
next
|
520
|
+
end
|
521
|
+
end
|
522
|
+
|
523
|
+
CLI::with_status("Deleting...") do
|
524
|
+
if what == :post
|
525
|
+
@@connection.delete_post id.to_i
|
526
|
+
elsif what == :page
|
527
|
+
@@connection.delete_page id.to_i
|
528
|
+
end
|
529
|
+
end
|
530
|
+
end
|
531
|
+
end
|
532
|
+
|
533
|
+
# Show last `ammount` of posts/pages in reverse order of
|
534
|
+
# publication.
|
535
|
+
#
|
536
|
+
def list(what, ammount)
|
537
|
+
Quickpress::startup
|
538
|
+
|
539
|
+
elements = nil
|
540
|
+
if what == :post
|
541
|
+
CLI::with_status("Retrieving posts...") do
|
542
|
+
elements = @@connection.get_posts ammount
|
543
|
+
end
|
544
|
+
|
545
|
+
elsif what == :page
|
546
|
+
CLI::with_status("Retrieving pages...") do
|
547
|
+
elements = @@connection.get_pages ammount
|
548
|
+
end
|
549
|
+
end
|
550
|
+
|
551
|
+
# Ugly as fuark :(
|
552
|
+
puts "+-----+---------------------------------------+-----------------------+--------+"
|
553
|
+
puts "| ID|Title |Date |Status |"
|
554
|
+
puts "+-----+---------------------------------------+-----------------------+--------+"
|
555
|
+
elements.each do |post|
|
556
|
+
puts sprintf("|%5d|%-39s|%s|%-8s|", post["post_id"].to_i,
|
557
|
+
post["post_title"],
|
558
|
+
post["post_date"].to_time,
|
559
|
+
post["post_status"])
|
560
|
+
end
|
561
|
+
puts "+-----+---------------------------------------+-----------------------+--------+"
|
562
|
+
end
|
563
|
+
|
564
|
+
def list_markup
|
565
|
+
puts "Name (file extension)"
|
566
|
+
puts
|
567
|
+
|
568
|
+
@@supported_markup.each do |m|
|
569
|
+
puts "* #{m[0]} (#{m[1]})"
|
570
|
+
end
|
571
|
+
end
|
572
|
+
|
573
|
+
private
|
574
|
+
module_function
|
575
|
+
|
576
|
+
# Initializes everything based on the config file or
|
577
|
+
# simply by asking the user.
|
578
|
+
def startup
|
579
|
+
Quickpress::first_time if @@default_site.nil?
|
580
|
+
|
581
|
+
puts "Using site '#{@@default_site}'"
|
582
|
+
|
583
|
+
Quickpress::authenticate
|
584
|
+
|
585
|
+
CLI::with_status("Connecting...") do
|
586
|
+
@@connection ||= Wordpress.new(@@default_site, @@username, @@password)
|
587
|
+
end
|
588
|
+
end
|
589
|
+
|
590
|
+
# Gets username and password.
|
591
|
+
#
|
592
|
+
# First, try getting from environment variables
|
593
|
+
# `QP_USERNAME` and `QP_PASSWORD`.
|
594
|
+
#
|
595
|
+
# If that fails, asks to the user.
|
596
|
+
def authenticate
|
597
|
+
@@username ||= ENV["QP_USERNAME"]
|
598
|
+
@@password ||= ENV["QP_PASSWORD"]
|
599
|
+
|
600
|
+
@@username ||= CLI::get("Username:")
|
601
|
+
@@password ||= CLI::get_secret("Password:")
|
602
|
+
end
|
603
|
+
end
|
604
|
+
|