1 # Walk the directory (and subdirectories), identifying books.
4 # .../AuthorName/Title_of_the_Awesome_Book.ext
6 # Author is given as FirstLast. For example,
7 # Robert Anson Heinlein is RobertHeinlein, and
8 # JKRowling is JoanneRowling.
10 # Book titles have spaces replaced with underscores,
11 # and punctuation [,!?'] replaced with hyphens.
13 # If the book forms part of a series, then an all-capitals
14 # series designator, followed by a numeric volume number,
15 # followed by an underscore, is prefixed to the name.
16 # For example, Hardy Boys' volume 1, The Tower Treasure,
17 # is rendered as .../FranklinDixon/HB001_The_Tower_Treasure.epub
18 # and Mrs. Pollifax volume 6, On the China Station, is
19 # .../DorothyGilman/P06_On_the_China_Station.epub.
21 require_relative 'book'
22 require_relative 'book_loader'
23 require_relative 'store'
26 def initialize(config_file, root)
29 @config_file = config_file
38 @threads << Thread.new do
39 BookLoader.new(@config_file, @queue).run
44 @files = remove_duplicates(@files)
45 for file in @files.sort()
46 if Book.can_handle?(file) && (!is_duplicate?(file))
47 # Queue this book to be loaded and added to the DB by a BookLoader thread
52 @threads.count.times { @queue << BookLoader::DONE_MARKER }
54 @threads.each { |t| t.join }
57 # Duplicate versions of a text are named
59 # Where suffix is one of bis, ter, quater, quinquies
60 # for the 2nd, 3rd, 4th or 5th variant respectively.
61 def is_duplicate?(file)
63 suffix = ['_bis.', '_ter.', '_quater.', '_quinquies.']
73 def remove_duplicates(files)
76 if Book.can_handle?(file)
77 key = File.dirname(file) + '/' + File.basename(file, '.*')
78 if unique.has_key?(key)
79 new_ext = File.extname(file)
80 old_ext = File.extname(unique[key])
81 if ('.pdf' == old_ext) && ('.epub' == new_ext)
82 # Prefer EPUB over PDF
83 puts 'REPLACED ' + unique[key].to_s + ' with ' + file.to_s
86 puts 'DROPPED ' + file.to_s + " because it's superceded by " + unique[key].to_s
99 children = Dir.entries(path)
100 for child in children
101 fullName = (path.chomp("/")) + "/" + child
102 if (File.directory?(fullName)) and (child != ".") and (child != "..") and (!File.symlink?(fullName))
104 if (sub != nil) and (sub.length > 0)
107 elsif (! File.directory?(fullName))
108 result.push(fullName)
115 # TOOD: make this (auto?) configurable