Skip to content

Instantly share code, notes, and snippets.

@ntalbott
Created March 12, 2013 04:14
Show Gist options
  • Save ntalbott/5140300 to your computer and use it in GitHub Desktop.
Save ntalbott/5140300 to your computer and use it in GitHub Desktop.
Syncs a directory structure to a non-touch Kindle and writes collections metadata.
#!/usr/bin/env ruby
require "rubygems"
require "pathname"
require "fileutils"
require "json"
require "digest/sha1"
require "awesome_print"
class Collections
def initialize(path_to_collections_file)
@collections_file = path_to_collections_file
@data = JSON.parse(File.read(@collections_file))
@collections = Hash.new{|h,k| h[k] = []}
end
def add(path)
return if path.dirname.to_s == "."
collection = path.dirname.to_s.split("/").join("_")
@collections[collection] << path
end
def write!
@collections.each do |collection, contents|
name = collection + "@"
entry = (@data[name] ||= {})
items = (entry["items"] ||= [])
items = items | contents.collect{|e| sha_for(e)}
@data[name]["items"] = items
end
File.open(@collections_file, "w") do |f|
f.puts(@data.to_json)
end
end
private
def sha_for(path)
sha = "*" + Digest::SHA1.hexdigest("/mnt/us/documents/#{path.basename}")
puts "#{path}: #{sha}"
sha
end
end
def usage!
puts "Usage: ksync <books directory> [Kindle volume]"
exit!
end
def clean_file_name(name)
name.to_s.gsub(/[_\- ]/, '')
end
source_dir = Pathname.new(ARGV.first || usage!)
volume = Pathname.new(ARGV[1] || "/Volumes/Kindle")
source_dir.exist? || abort("Source directory not found")
volume.exist? || abort("Kindle volume not found")
collections = Collections.new(volume + "system/collections.json")
Dir[source_dir + "**/*"].each do |file|
file = Pathname.new(file)
next if file.directory?
next unless %w(.pdf .mobi).include?(file.extname)
path = file.relative_path_from(source_dir)
destination = volume + "documents" + clean_file_name(path.basename)
if destination.exist?
if destination.size != file.size
count = Dir[destination.dirname + destination.basename(destination.extname) + "*"].size
real_destination = Pathname.new(destination.dirname + (destination.basename(destination.extname).to_s + "_" + (count + 1).to_s + destination.extname))
FileUtils.cp(file, real_destination)
else
real_destination = destination
end
else
FileUtils.cp(file, destination)
real_destination = destination
end
collections.add(path.dirname + real_destination.basename)
end
collections.write!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment