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