ebook_library 0.3.0
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 +9 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/README.md +48 -0
- data/Rakefile +18 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/ebook_library.gemspec +31 -0
- data/lib/ebook_library.rb +21 -0
- data/lib/ebook_library/ebook.rb +70 -0
- data/lib/ebook_library/ebook_factory.rb +41 -0
- data/lib/ebook_library/factory/epub.rb +19 -0
- data/lib/ebook_library/factory/mobi.rb +18 -0
- data/lib/ebook_library/factory/pdf.rb +19 -0
- data/lib/ebook_library/gatherer.rb +37 -0
- data/lib/ebook_library/version.rb +3 -0
- metadata +172 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 846024e35f3f3460e2e072b4baf1bd272f5a9091
|
4
|
+
data.tar.gz: a52d936666c0c3f926f506b394a531f69d58f534
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 68afad92c71bfb5a7acd49935accab6c6285b53d5e16fe33e5b66831cff91e338e564313d8a2e7a2a643fab39a875843c87f866eac305c6f370fd6ce99f5ca1c
|
7
|
+
data.tar.gz: be32071a4b316c076d4ebe01429095df539fb0379c4ab3d70cc49589eefc22b5bc754534452f759c11c0818ba4a2afb4f2cbe689c2aecf0bef2c496a901555d4
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# EbookLibrary
|
2
|
+
|
3
|
+
generate an organized library from a local ebook directory.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'ebook_library'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install ebook_library
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
in a rake task you might want to run
|
24
|
+
|
25
|
+
```
|
26
|
+
EbookLibrary::Gatherer.gather
|
27
|
+
```
|
28
|
+
|
29
|
+
## Development
|
30
|
+
|
31
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then,
|
32
|
+
run `rake false` to run the tests. You can also run `bin/console` for an
|
33
|
+
interactive prompt that will allow you to experiment.
|
34
|
+
|
35
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
36
|
+
To release a new version, update the version number in `version.rb`, and then
|
37
|
+
run `bundle exec rake release`, which will create a git tag for the version,
|
38
|
+
push git commits and tags, and push the `.gem` file to
|
39
|
+
[rubygems.org](https://rubygems.org).
|
40
|
+
|
41
|
+
## Contributing
|
42
|
+
|
43
|
+
Bug reports and pull requests are welcome on GitHub at
|
44
|
+
https://github.com/[USERNAME]/ebook_library. This project is intended to be a
|
45
|
+
safe, welcoming space for collaboration, and contributors are expected to
|
46
|
+
adhere to the [Contributor Covenant](contributor-covenant.org) code of
|
47
|
+
conduct.
|
48
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'ebook_library'
|
4
|
+
|
5
|
+
Bundler::GemHelper.install_tasks
|
6
|
+
|
7
|
+
RSpec::Core::RakeTask.new do |t|
|
8
|
+
t.rspec_opts = %w(--format documentation --colour)
|
9
|
+
end
|
10
|
+
|
11
|
+
task :default => 'spec'
|
12
|
+
|
13
|
+
# example rake task
|
14
|
+
task :generate => :environment do
|
15
|
+
require 'json'
|
16
|
+
ebooks = EbookLibrary.dump
|
17
|
+
File.open("./books.json", 'w') { |file| file.write(ebooks) }
|
18
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "ebook_library"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ebook_library/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ebook_library"
|
8
|
+
spec.version = EbookLibrary::VERSION
|
9
|
+
spec.authors = ["tippenein"]
|
10
|
+
spec.email = ["brady.ouren@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = "generate an organized library from a local ebook directory."
|
13
|
+
|
14
|
+
spec.description = "generate an organized library from a local ebook directory."
|
15
|
+
spec.homepage = "https://github.com/tippenein/ebook_library"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
23
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
+
spec.add_development_dependency "rspec"
|
25
|
+
spec.add_development_dependency "byebug"
|
26
|
+
|
27
|
+
spec.add_dependency "mobi"
|
28
|
+
spec.add_dependency "epub-parser"
|
29
|
+
spec.add_dependency "pdf-reader"
|
30
|
+
spec.add_dependency "monadic"
|
31
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "ebook_library/version"
|
2
|
+
require "ebook_library/gatherer"
|
3
|
+
require "ebook_library/ebook"
|
4
|
+
require "ebook_library/ebook_factory"
|
5
|
+
require "ebook_library/factory/epub"
|
6
|
+
require "ebook_library/factory/mobi"
|
7
|
+
require "ebook_library/factory/pdf"
|
8
|
+
|
9
|
+
module EbookLibrary
|
10
|
+
def self.default_path
|
11
|
+
File.join ENV["HOME"], "Documents/ebooks"
|
12
|
+
end
|
13
|
+
|
14
|
+
#TODO allow different outputs
|
15
|
+
def self.dump(type=:json)
|
16
|
+
require 'json' if type.to_sym == :json
|
17
|
+
Gatherer.new.gather.to_json
|
18
|
+
end
|
19
|
+
|
20
|
+
class InvalidPath < StandardError; end
|
21
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'epub/parser'
|
2
|
+
require 'pdf-reader'
|
3
|
+
require 'mobi'
|
4
|
+
|
5
|
+
module EbookLibrary
|
6
|
+
class Ebook
|
7
|
+
attr_reader :raw_ebook, :path, :adapter
|
8
|
+
def initialize(ebook_path)
|
9
|
+
@path = ebook_path
|
10
|
+
@raw_ebook = File.open ebook_path
|
11
|
+
@adapter = get_adapter
|
12
|
+
end
|
13
|
+
|
14
|
+
def title
|
15
|
+
has_metadata? ? adapter.title : "unknown"
|
16
|
+
end
|
17
|
+
|
18
|
+
def author
|
19
|
+
has_metadata? ? adapter.author : "unknown"
|
20
|
+
end
|
21
|
+
|
22
|
+
def format
|
23
|
+
@format ||= File.extname(path).gsub(/^./, "")
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_hash
|
27
|
+
Hash[attrs.map{|attr| [attr, send(attr)]}] if valid?
|
28
|
+
end
|
29
|
+
|
30
|
+
def has_metadata?
|
31
|
+
!metadata.nil?
|
32
|
+
end
|
33
|
+
|
34
|
+
def valid?
|
35
|
+
EbookFactory.supported_types.include?(format)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def get_adapter
|
41
|
+
EbookFactory.new(format, metadata)
|
42
|
+
end
|
43
|
+
|
44
|
+
def attrs
|
45
|
+
[:title, :author, :format, :path]
|
46
|
+
end
|
47
|
+
|
48
|
+
def metadata
|
49
|
+
%i(parse_mobi parse_epub parse_pdf).inject(nil) do |parsed, parser|
|
50
|
+
begin
|
51
|
+
parsed || send(parser)
|
52
|
+
rescue
|
53
|
+
nil
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def parse_epub
|
59
|
+
::EPUB::Parser.parse(path).metadata
|
60
|
+
end
|
61
|
+
|
62
|
+
def parse_mobi
|
63
|
+
::Mobi.metadata raw_ebook
|
64
|
+
end
|
65
|
+
|
66
|
+
def parse_pdf
|
67
|
+
::PDF::Reader.new(raw_book).metadata
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'monadic'
|
2
|
+
module EbookLibrary
|
3
|
+
class EbookFactory
|
4
|
+
attr_reader :adapter
|
5
|
+
def initialize(format, metadata)
|
6
|
+
raise UnsupportedFormatError unless %w(epub mobi pdf).include? format
|
7
|
+
@adapter = for_type(format).new(metadata)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.supported_types
|
11
|
+
%w(epub mobi pdf)
|
12
|
+
end
|
13
|
+
|
14
|
+
def title
|
15
|
+
Maybe(adapter).title._("untitled").encode('UTF-8', encode_options)
|
16
|
+
end
|
17
|
+
|
18
|
+
def author
|
19
|
+
Maybe(adapter).author._("").encode('UTF-8', encode_options)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
#TODO move these to config
|
24
|
+
def encode_options
|
25
|
+
{invalid: :replace, undef: :replace, replace: '?'}
|
26
|
+
end
|
27
|
+
|
28
|
+
def for_type(format)
|
29
|
+
case format
|
30
|
+
when 'epub'
|
31
|
+
Factory::Epub
|
32
|
+
when 'mobi', 'azw'
|
33
|
+
Factory::Mobi
|
34
|
+
when 'pdf'
|
35
|
+
Factory::Pdf
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class UnsupportedFormatError < StandardError; end
|
41
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module EbookLibrary
|
2
|
+
module Factory
|
3
|
+
class Epub
|
4
|
+
attr_reader :metadata
|
5
|
+
def initialize(metadata)
|
6
|
+
@metadata = metadata
|
7
|
+
end
|
8
|
+
|
9
|
+
def author
|
10
|
+
metadata.creators.map(&:content).join(" ")
|
11
|
+
end
|
12
|
+
|
13
|
+
def title
|
14
|
+
metadata.title || metadata.titles
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# this could possibly use the ebook-meta tool
|
2
|
+
# http://manual.calibre-ebook.com/cli/ebook-meta.html
|
3
|
+
#
|
4
|
+
# reference:
|
5
|
+
# http://wiki.mobileread.com/wiki/MOBI
|
6
|
+
|
7
|
+
module EbookLibrary
|
8
|
+
class Gatherer
|
9
|
+
attr_accessor :path
|
10
|
+
|
11
|
+
def initialize(path=EbookLibrary.default_path)
|
12
|
+
@path = path if File.exist?(path)
|
13
|
+
raise InvalidPath if @path.nil?
|
14
|
+
end
|
15
|
+
|
16
|
+
def gather
|
17
|
+
results = gather_ebooks.map do |book_path|
|
18
|
+
begin
|
19
|
+
ebook = Ebook.new(book_path)
|
20
|
+
ebook.to_hash
|
21
|
+
rescue EbookLibrary::UnsupportedFormatError
|
22
|
+
puts "skipping: " + book_path
|
23
|
+
end
|
24
|
+
end
|
25
|
+
{ books: results.compact }
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# returns [FilePath]
|
31
|
+
def gather_ebooks
|
32
|
+
Dir.glob("#{path}/**/*").inject([]) do |paths, book_path|
|
33
|
+
paths << book_path
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
metadata
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ebook_library
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- tippenein
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-01-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.10'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.10'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: byebug
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: mobi
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: epub-parser
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: pdf-reader
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: monadic
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description: generate an organized library from a local ebook directory.
|
126
|
+
email:
|
127
|
+
- brady.ouren@gmail.com
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- ".gitignore"
|
133
|
+
- ".rspec"
|
134
|
+
- ".travis.yml"
|
135
|
+
- Gemfile
|
136
|
+
- README.md
|
137
|
+
- Rakefile
|
138
|
+
- bin/console
|
139
|
+
- bin/setup
|
140
|
+
- ebook_library.gemspec
|
141
|
+
- lib/ebook_library.rb
|
142
|
+
- lib/ebook_library/ebook.rb
|
143
|
+
- lib/ebook_library/ebook_factory.rb
|
144
|
+
- lib/ebook_library/factory/epub.rb
|
145
|
+
- lib/ebook_library/factory/mobi.rb
|
146
|
+
- lib/ebook_library/factory/pdf.rb
|
147
|
+
- lib/ebook_library/gatherer.rb
|
148
|
+
- lib/ebook_library/version.rb
|
149
|
+
homepage: https://github.com/tippenein/ebook_library
|
150
|
+
licenses: []
|
151
|
+
metadata: {}
|
152
|
+
post_install_message:
|
153
|
+
rdoc_options: []
|
154
|
+
require_paths:
|
155
|
+
- lib
|
156
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - ">="
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '0'
|
161
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - ">="
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
requirements: []
|
167
|
+
rubyforge_project:
|
168
|
+
rubygems_version: 2.4.5
|
169
|
+
signing_key:
|
170
|
+
specification_version: 4
|
171
|
+
summary: generate an organized library from a local ebook directory.
|
172
|
+
test_files: []
|