bin/klipbook in klipbook-2.0.0 vs bin/klipbook in klipbook-2.1.0
- old
+ new
@@ -1,127 +1,223 @@
#!/usr/bin/env ruby
$LOAD_PATH << File.expand_path('../../lib', __FILE__)
-require 'gli'
require 'klipbook'
+require 'slop'
-include GLI::App
+##########
+# Helpers
+##########
-program_desc "Collates the clippings you've saved on your Kindle into a nice html summary for each book."
+def get_book_source(opts)
+ exit_unless_valid_source(opts)
-SOURCE_HELP = "Two sources are currently supported: a file from a Kindle device and the Kindle site itself.\n\n" +
- "Example file formats:\n\n" +
- " file:path/to/my-clippings-file.txt\n\n" +
- " site:my-kindle-user@blah.com:my-kindle-password\n\n" +
- "Note that source and output file defaults can be stored in a file called ~/.klipbookrc\n\n" +
- "This file is YAML formatted e.g.\n\n" +
- "source: site:my-kindle-user@blah.com:my-kindle-password\n\n" +
- "output: my/default/output/directory"
+ max_books = opts[:number].to_i
-version Klipbook::VERSION
+ unless max_books > 0
+ $stderr.puts "Error: Specify a number of books greater than 0"
+ exit 127
+ end
-desc 'Number of books to process'
-arg_name 'count'
-default_value 1
-flag [:n, :'num-books']
+ get_file_source(infile(opts), max_books) || get_site_source(credentials(opts), max_books)
+end
-desc 'Collate your clippings into a single json file'
-arg_name 'source'
-long_desc "Clippings are fetched from the specified source, collated, and written into a single json file.\n\n" +
- SOURCE_HELP
-command :collate do |c|
+def exit_unless_valid_source(opts)
+ unless opts[:infile] || opts[:credentials] || CONFIG[:credentials]
+ $stderr.puts "Error: #{SOURCE_HELP}"
+ exit 127
+ end
+end
- c.desc 'Specify the name of the json file to be written to.'
- c.arg_name 'File-name'
- c.flag [:c, :'output-file']
+def get_site_source(creds, max_books)
+ return nil unless creds
- c.desc 'Force overwrite of any existing book entries within the output file'
- c.switch [:f, :force]
-
- c.action do |globals,options,args|
- book_file_path = output_file(options)
- books = fetch_books(args, globals)
- Klipbook::Commands::Collate.new(books, book_file(book_file_path)).call(book_file_path, options[:f])
+ unless creds =~ /(.+):(.+)/
+ $stderr.puts "Error: your credentials need to be in username:password format."
+ exit 127
end
+
+ username = $1
+ password = $2
+ Klipbook::Sources::AmazonSite::SiteScraper.new(username, password, max_books)
end
-desc 'Pretty print your clippings into a html file for each book'
-arg_name 'source'
-long_desc "Clippings are fetched from the specified source before being written to html " +
- "files in the output directory.\n\n" + SOURCE_HELP
-command :pprint do |c|
+def get_file_source(file, max_books)
+ return nil unless file
- c.desc 'Override the directory path where html files are written'
- c.arg_name 'Directory'
- c.flag [:o, :'output-dir']
+ Klipbook::Sources::KindleDevice::File.new(file, max_books)
+end
- c.desc 'Force overwrite of any existing files'
- c.switch [:f, :force]
+def fetch_books(opts)
+ get_book_source(opts).books
+end
- c.action do |globals,options,args|
- books = fetch_books(args, globals)
- Klipbook::Commands::PrettyPrint.new(books).call(output_dir(options), options[:f])
+def open_infile(file_path)
+ return nil unless file_path
+
+ unless File.exists? file_path
+ $stderr.puts "Error: could not open #{file_path}"
+ exit 127
end
+
+ File.open(file_path, "r")
end
-desc 'List available books'
-arg_name 'source'
-long_desc "List the books from the specified source to screen.\n\n" + SOURCE_HELP
-command :list do |c|
- c.action do |globals,options,args|
- books = fetch_books(args, globals)
- Klipbook::Commands::ListBooks.new(books).call
+def raw_json_from_file(file_path)
+ File.open(file_path, 'r') do |f|
+ f.read
end
+rescue
+ ""
end
-pre do |globals,command,options,args|
- unless source_spec(args)
- raise InvalidSourceError
- end
+def book_file(file_path)
+ Klipbook::Collate::BookFile.from_json(raw_json_from_file(file_path))
+end
- odir = output_dir(options)
- if odir && !File.exists?(odir)
- raise "Output directory doesn't exist: #{odir}"
- end
+#########
+# Params
+#########
- if globals[:n].to_i == 0
- raise 'Specify a number of books greater than 0'
- end
-
- true
+def infile(opts)
+ open_infile(opts[:infile])
end
-on_error do |exception|
- true
+def credentials(opts)
+ puts "Using credentials from ~/.klipbookrc" if !opts[:credentials] && CONFIG[:credentials]
+
+ opts[:credentials] || CONFIG[:credentials]
end
-def book_file(file_path)
- raw_json = if File.exist?(file_path)
- File.open(file_path, 'r') do |f|
- f.read
- end
- else
- ''
- end
+def ensure_outfile(opts)
+ unless opts[:outfile] || CONFIG[:outfile]
+ $stderr.puts("Error: Please specify an outfile.")
+ exit(127)
+ end
- Klipbook::Collate::BookFile.from_json(raw_json)
+ outfile_path(opts)
end
-def source_spec(args)
- @source_spec ||= (args[0] || Klipbook::Config.new.read[:source])
+def outfile_path(opts)
+ puts "Using outfile from ~/.klipbookrc" if !opts[:outfile] && CONFIG[:outfile]
+
+ opts[:outfile] || CONFIG[:outfile]
end
-def fetch_books(args, globals)
- Klipbook::Sources::BookSource.new(source_spec(args), globals[:n].to_i).books
+def ensure_outdir(opts)
+ unless opts[:outdir] || CONFIG[:outdir]
+ $stderr.puts("Error: Please specify an outdir.")
+ exit(127)
+ end
+
+ outdir = outdir_path(opts)
+
+ unless File.exists?(outdir)
+ $stderr.puts("Error: Outdir does not exist.")
+ exit(127)
+ end
+
+ outdir
end
-def output_dir(options)
- @output_dir ||= (options[:o] || Klipbook::Config.new.read[:output] || Dir.pwd)
+def outdir_path(opts)
+ puts "Using outdir from ~/.klipbookrc" if !opts[:outdir] && CONFIG[:outdir]
+
+ opts[:outdir] || CONFIG[:outdir] || Dir.pwd
end
-def output_file(options)
- @output_file ||= (options[:c] || Klipbook::Config.new.read[:output_file] || File.join(Dir.pwd, 'books.json'))
+##########
+# Go time
+##########
+
+CONFIG = Klipbook::Config.new.read
+
+DEFAULT_MAXBOOKS=5
+SOURCE_HELP = "You must specify either `--credentials` or `--infile` as an input."
+
+CONFIG_HELP = "Note that credentials, outdir, and outfile defaults can be stored in a file called ~/.klipbookrc\n\n" +
+ "This file is YAML formatted e.g.\n\n" +
+ ":credentials: my-kindle-user@blah.com:my-kindle-password\n" +
+ ":outdir: my/default/output/directory\n" +
+ ":outfile: my/default/output/file.json\n"
+
+def banner_for_command(command, description)
+ "Usage: klipbook #{command} [options]\n\n#{description}\n\n#{SOURCE_HELP}\n"
end
-exit run(ARGV)
+opts = Slop.parse(help: true) do
+ banner "Usage: klipbook <command> [options]\n\n" +
+ "Klipbook pretty prints the clippings you've saved on your Kindle into JSON or pretty html.\n\n" +
+ CONFIG_HELP + "\n"
+
+ on :v, :version, "Print the version." do
+ puts "Klipbook version #{Klipbook::VERSION}"
+ end
+
+ command "list" do
+ desc = "List the books on the site or in the clippings file."
+
+ banner banner_for_command("list", desc)
+
+ description desc
+
+ on :c, :credentials=, "<username>:<password> for Kindle site"
+ on :i, :infile=, "Input file (default STDIN)"
+ on :n, :number=, "Maximum number of books to list (default is #{DEFAULT_MAXBOOKS})", default: DEFAULT_MAXBOOKS
+
+ run do |opts, args|
+ books = fetch_books(opts)
+ Klipbook::Commands::ListBooks.new(books).call
+ end
+ end
+
+ command "tojson" do
+ desc = "Print book highlights as JSON. Note that this will update an existing JSON file in place with new entries."
+
+ banner banner_for_command("tojson", desc)
+
+ description desc
+
+ on :c, :credentials=, "<username>:<password> for Kindle site"
+ on :i, :infile=, "Input file (default STDIN)"
+ on :n, :number=, "Maximum number of books to print as json (default is #{DEFAULT_MAXBOOKS})", default: DEFAULT_MAXBOOKS
+ on :o, :outfile=, "Output JSON file (default STDOUT)"
+ on :f, :force, "Force overwrite of any existing book entries within the output file"
+
+ run do |opts, args|
+ outfile_path = ensure_outfile(opts)
+
+ books = fetch_books(opts)
+
+ Klipbook::Commands::Collate.new(books, book_file(outfile_path)).call(outfile_path, opts[:force])
+ end
+ end
+
+ command "tohtml" do
+ desc = "Print book highlights as HTML."
+
+ banner banner_for_command("tohtml", desc)
+
+ description desc
+
+ on :c, :credentials=, "<username>:<password> for Kindle site"
+ on :i, :infile=, "Input file (default STDIN)"
+ on :n, :number=, "Maximum number of books to print as html (default is #{DEFAULT_MAXBOOKS})", default: DEFAULT_MAXBOOKS
+ on :o, :outdir=, "Directory to write HTML files to (default pwd)"
+ on :f, :force, "Force overwrite of existing files"
+
+ run do |opts, args|
+ books = fetch_books(opts)
+
+ outdir_path = ensure_outdir(opts)
+
+ Klipbook::Commands::PrettyPrint.new(books).call(outdir_path, opts[:force])
+ end
+ end
+
+ # Default action is to output help
+ run do |opts, args|
+ puts opts.help
+ end
+end