kindle-notebook 0.2.1 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +9 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +25 -1
- data/README.md +42 -4
- data/kindle-notebook.gemspec +44 -0
- data/lib/kindle-notebook.rb +24 -22
- data/lib/kindle_notebook/amazon_auth.rb +38 -21
- data/lib/kindle_notebook/book.rb +1 -2
- data/lib/kindle_notebook/client.rb +55 -11
- data/lib/kindle_notebook/highlights.rb +3 -2
- data/lib/kindle_notebook/version.rb +1 -1
- metadata +3 -4
- data/kindle_notebook-0.2.0.gem +0 -0
- data/kindle_notebook-0.2.1.gem +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fdf9f8aae86d86694218ea71a942afad7dc5867970b79671f0dede3372bdb5ee
|
4
|
+
data.tar.gz: 6a132ae2b4b7291693c0e72992cb02b59248a908fdb0ded0fd220a6c20de2646
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab04dbcf4e7e721f8bd5f2f85b879998ca6f235b8485e55b82d3ab07a8273bf90740f14f9d40a6c064c2ecab136e64a5294138e0d54c6411633390456db69ae4
|
7
|
+
data.tar.gz: 15b4d1b7ab4d83bcb98d7b092734ae3d617ae7b4da6c9b3d08c32c2caadd79fadd10768d5334cbb29fd6e0b4794ee14d38b3dcfff3fd0bb85b4832b0621e523f
|
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
kindle-notebook (0.
|
4
|
+
kindle-notebook (0.3.1)
|
5
5
|
capybara (~> 3.39)
|
6
6
|
capybara-sessionkeeper (~> 0.2.0)
|
7
7
|
selenium-webdriver (~> 4.9)
|
@@ -25,12 +25,27 @@ GEM
|
|
25
25
|
capybara
|
26
26
|
selenium-webdriver
|
27
27
|
coderay (1.1.3)
|
28
|
+
cookiejar (0.3.3)
|
28
29
|
diff-lcs (1.5.0)
|
29
30
|
dotenv (2.8.1)
|
31
|
+
em-http-request (1.1.7)
|
32
|
+
addressable (>= 2.3.4)
|
33
|
+
cookiejar (!= 0.3.1)
|
34
|
+
em-socksify (>= 0.3)
|
35
|
+
eventmachine (>= 1.0.3)
|
36
|
+
http_parser.rb (>= 0.6.0)
|
37
|
+
em-socksify (0.3.2)
|
38
|
+
eventmachine (>= 1.0.0.beta.4)
|
39
|
+
em-synchrony (1.0.6)
|
40
|
+
eventmachine (>= 1.0.0.beta.1)
|
41
|
+
eventmachine (1.2.7)
|
42
|
+
eventmachine_httpserver (0.2.1)
|
43
|
+
http_parser.rb (0.6.0)
|
30
44
|
json (2.6.3)
|
31
45
|
matrix (0.4.2)
|
32
46
|
method_source (1.0.0)
|
33
47
|
mini_mime (1.1.2)
|
48
|
+
multi_json (1.15.0)
|
34
49
|
nokogiri (1.14.3-x86_64-linux)
|
35
50
|
racc (~> 1.4)
|
36
51
|
parallel (1.22.1)
|
@@ -40,6 +55,14 @@ GEM
|
|
40
55
|
coderay (~> 1.1)
|
41
56
|
method_source (~> 1.0)
|
42
57
|
public_suffix (5.0.1)
|
58
|
+
puffing-billy (3.1.0)
|
59
|
+
addressable (~> 2.5)
|
60
|
+
em-http-request (~> 1.1, >= 1.1.0)
|
61
|
+
em-synchrony
|
62
|
+
eventmachine (~> 1.2)
|
63
|
+
eventmachine_httpserver
|
64
|
+
http_parser.rb (~> 0.6.0)
|
65
|
+
multi_json
|
43
66
|
racc (1.6.2)
|
44
67
|
rack (3.0.7)
|
45
68
|
rack-test (2.1.0)
|
@@ -98,6 +121,7 @@ DEPENDENCIES
|
|
98
121
|
dotenv (~> 2.8, >= 2.8.1)
|
99
122
|
kindle-notebook!
|
100
123
|
pry (~> 0.14.2)
|
124
|
+
puffing-billy (~> 3.1)
|
101
125
|
rake (~> 13.0)
|
102
126
|
rspec (~> 3.0)
|
103
127
|
rubocop (~> 1.21)
|
data/README.md
CHANGED
@@ -18,12 +18,37 @@ If bundler is not being used to manage dependencies, install the gem by executin
|
|
18
18
|
$ gem install kindle-notebook
|
19
19
|
```
|
20
20
|
|
21
|
+
## Configuration
|
22
|
+
|
23
|
+
You can either create a `.env` file and add your credentials, the default values will be fetched from this file, or configure the gem, for example in an initializer file.
|
24
|
+
|
25
|
+
```rb
|
26
|
+
KindleNotebook.configure do |config|
|
27
|
+
config.url = "https://read.amazon.com/"
|
28
|
+
config.login = ENV["AMAZON_EMAIL"]
|
29
|
+
config.password = ENV["AMAZON_PASSWORD"]
|
30
|
+
config.selenium_driver = :firefox
|
31
|
+
config.headless_mode = false
|
32
|
+
config.min_highlight_words = 1
|
33
|
+
config.max_highlight_words = 3
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
37
|
+
The configuration options `min_highlight_words` and `max_highlight_words` determine the range for a highlight's word count. Highlights with a word count outside this range will not be considered will be filtered out.
|
38
|
+
|
21
39
|
## Usage
|
22
40
|
|
23
|
-
|
41
|
+
Sign in:
|
24
42
|
```rb
|
25
|
-
|
26
|
-
|
43
|
+
client = KindleNotebook::Client.new
|
44
|
+
client.sign_in
|
45
|
+
```
|
46
|
+
|
47
|
+
Get the highlights from a book:
|
48
|
+
```rb
|
49
|
+
books = client.books
|
50
|
+
book = books.first
|
51
|
+
book.fetch_highlights
|
27
52
|
book.highlights
|
28
53
|
```
|
29
54
|
|
@@ -59,7 +84,7 @@ Highlight:
|
|
59
84
|
Book CSV:
|
60
85
|
```csv
|
61
86
|
text,page,context,book_asin,raw_text,raw_context
|
62
|
-
journald,120
|
87
|
+
journald,120,"If you get stuck, the logging component of systemd, called journald, can also help.",B09FJ3411G,"journald,","used, for example. If you get stuck, the logging component of systemd, called journald, can also help. This journald command displays the last 20 entries in the"
|
63
88
|
swarm,225,"Docker Swarm In this chapter, you're going to learn how to create and use a Docker",B09FJ3411G,swarm.,"Docker Swarm In this chapter, you're going to learn how to create and use a Docker"
|
64
89
|
```
|
65
90
|
|
@@ -69,6 +94,19 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
69
94
|
|
70
95
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
71
96
|
|
97
|
+
### Testing
|
98
|
+
|
99
|
+
This gem is using [puffing-billy](https://github.com/oesmith/puffing-billy) for testing which needs the geckodriver executable. It can be installed with:
|
100
|
+
```sh
|
101
|
+
$ sudo apt-get install firefox-geckodriver # or
|
102
|
+
$ brew install geckodriver
|
103
|
+
```
|
104
|
+
|
105
|
+
The executable should be in your `PATH`, if it is not you can run the following command (please adapt the location of the geckodriver executable with yours):
|
106
|
+
```sh
|
107
|
+
$ echo 'export PATH=$PATH:/home/user/.cache/selenium/geckodriver/linux64/0.33.0' >> ~/.zshrc
|
108
|
+
```
|
109
|
+
|
72
110
|
## Contributing
|
73
111
|
|
74
112
|
Bug reports and pull requests are welcome on GitHub at https://github.com/b1anca/kindle-notebook. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/b1anca/kindle-notebook/blob/master/CODE_OF_CONDUCT.md).
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/kindle_notebook/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "kindle-notebook"
|
7
|
+
spec.version = KindleNotebook::VERSION
|
8
|
+
spec.authors = ["Bianca Vieira"]
|
9
|
+
spec.email = ["bncvr@outlook.com"]
|
10
|
+
|
11
|
+
spec.summary = "Kindle Notebook"
|
12
|
+
spec.description = "Fetch your Kindle Highlights along with their context using the Selenium Webdriver"
|
13
|
+
spec.homepage = "https://github.com/b1anca/kindle-notebook"
|
14
|
+
spec.license = "MIT"
|
15
|
+
spec.required_ruby_version = ">= 2.6.0"
|
16
|
+
|
17
|
+
# spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
|
18
|
+
|
19
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
20
|
+
spec.metadata["source_code_uri"] = "https://github.com/b1anca/kindle-notebook"
|
21
|
+
# spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
22
|
+
|
23
|
+
# Specify which files should be added to the gem when it is released.
|
24
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
25
|
+
spec.files = Dir.chdir(__dir__) do
|
26
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
27
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|circleci)|appveyor)})
|
28
|
+
end
|
29
|
+
end
|
30
|
+
spec.bindir = "exe"
|
31
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
32
|
+
spec.require_paths = ["lib"]
|
33
|
+
|
34
|
+
# Uncomment to register a new dependency of your gem
|
35
|
+
spec.add_dependency "capybara", "~> 3.39"
|
36
|
+
spec.add_dependency "capybara-sessionkeeper", "~> 0.2.0"
|
37
|
+
spec.add_dependency "selenium-webdriver", "~> 4.9"
|
38
|
+
|
39
|
+
spec.add_development_dependency "dotenv", "~> 2.8", ">= 2.8.1"
|
40
|
+
spec.add_development_dependency "pry", "~> 0.14.2"
|
41
|
+
|
42
|
+
# For more information and examples about making a new gem, check out our
|
43
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
44
|
+
end
|
data/lib/kindle-notebook.rb
CHANGED
@@ -4,6 +4,7 @@ require "capybara"
|
|
4
4
|
require "capybara/sessionkeeper"
|
5
5
|
require "csv"
|
6
6
|
require "selenium-webdriver"
|
7
|
+
require "dotenv"
|
7
8
|
|
8
9
|
require_relative "kindle_notebook/amazon_auth"
|
9
10
|
require_relative "kindle_notebook/book"
|
@@ -14,35 +15,36 @@ require_relative "kindle_notebook/highlights"
|
|
14
15
|
require_relative "kindle_notebook/highlight"
|
15
16
|
require_relative "kindle_notebook/version"
|
16
17
|
|
18
|
+
Dotenv.load
|
19
|
+
|
17
20
|
module KindleNotebook
|
18
21
|
class Error < StandardError; end
|
19
22
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
Capybara::Selenium::Driver.new(app, browser: :firefox, options: options)
|
23
|
+
class Configuration
|
24
|
+
attr_accessor :url, :login, :password, :selenium_driver, :headless_mode, :min_highlight_words,
|
25
|
+
:max_highlight_words
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@url = ENV["KINDLE_READER_URL"]
|
29
|
+
@login = ENV["AMAZON_EMAIL"]
|
30
|
+
@password = ENV["AMAZON_PASSWORD"]
|
31
|
+
@selenium_driver = ENV["SELENIUM_DRIVER"]
|
32
|
+
@headless_mode = ENV["HEADLESS_MODE"] == "true"
|
33
|
+
@min_highlight_words = ENV["MIN_HIGHLIGHT_WORDS"].to_i
|
34
|
+
@max_highlight_words = ENV["MAX_HIGHLIGHT_WORDS"].to_i
|
35
|
+
end
|
34
36
|
end
|
35
37
|
|
36
38
|
class << self
|
37
|
-
|
39
|
+
attr_writer :configuration
|
40
|
+
attr_accessor :session
|
41
|
+
end
|
38
42
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
end
|
43
|
+
def self.configuration
|
44
|
+
@configuration ||= KindleNotebook::Configuration.new
|
45
|
+
end
|
43
46
|
|
44
|
-
|
45
|
-
|
46
|
-
end
|
47
|
+
def self.configure
|
48
|
+
yield(configuration)
|
47
49
|
end
|
48
50
|
end
|
@@ -2,52 +2,69 @@
|
|
2
2
|
|
3
3
|
module KindleNotebook
|
4
4
|
class AmazonAuth
|
5
|
-
def initialize
|
6
|
-
@
|
5
|
+
def initialize(email:, password:)
|
6
|
+
@email = email
|
7
|
+
@password = password
|
7
8
|
end
|
8
9
|
|
9
10
|
def sign_in
|
10
|
-
|
11
|
-
|
11
|
+
session.visit(KindleNotebook.configuration.url)
|
12
|
+
if valid_cookies?
|
13
|
+
puts "Session restored!"
|
14
|
+
return session
|
15
|
+
end
|
12
16
|
|
13
17
|
submit_sign_in_form
|
14
|
-
|
15
|
-
|
18
|
+
submit_otp_form if mfa?
|
19
|
+
session.save_cookies
|
20
|
+
puts "You're signed in!"
|
16
21
|
end
|
17
22
|
|
18
23
|
private
|
19
24
|
|
20
|
-
attr_reader :
|
25
|
+
attr_reader :email, :password
|
26
|
+
|
27
|
+
def session
|
28
|
+
KindleNotebook.session
|
29
|
+
end
|
21
30
|
|
22
31
|
def valid_cookies?
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
32
|
+
session.find_latest_cookie_file
|
33
|
+
session.restore_cookies
|
34
|
+
session.refresh
|
35
|
+
session.has_current_path?("/kindle-library")
|
27
36
|
end
|
28
37
|
|
29
38
|
def submit_otp_form
|
30
39
|
print "Enter OTP: "
|
31
|
-
|
32
|
-
|
33
|
-
|
40
|
+
otp = gets.chomp
|
41
|
+
session.fill_in("auth-mfa-otpcode", with: otp)
|
42
|
+
session.first("#auth-signin-button").click
|
43
|
+
check_errors
|
34
44
|
end
|
35
45
|
|
36
46
|
def submit_sign_in_form
|
37
|
-
|
47
|
+
session.click_button("Sign in with your account", match: :first)
|
38
48
|
fill_in_credentials
|
39
|
-
|
40
|
-
|
41
|
-
|
49
|
+
session.check("rememberMe")
|
50
|
+
session.first("#signInSubmit").click
|
51
|
+
check_errors
|
42
52
|
end
|
43
53
|
|
44
54
|
def fill_in_credentials
|
45
|
-
|
46
|
-
|
55
|
+
session.fill_in("ap_email", with: email)
|
56
|
+
session.fill_in("ap_password", with: password)
|
47
57
|
end
|
48
58
|
|
49
59
|
def mfa?
|
50
|
-
|
60
|
+
session.current_path.match?(%r{ap/mfa})
|
61
|
+
end
|
62
|
+
|
63
|
+
def check_errors
|
64
|
+
return unless session.all("h4", text: "There was a problem").any?
|
65
|
+
|
66
|
+
message = session.all("div", class: "a-alert-content").map(&:text).join(", ") || "There was a problem"
|
67
|
+
raise StandardError, message
|
51
68
|
end
|
52
69
|
end
|
53
70
|
end
|
data/lib/kindle_notebook/book.rb
CHANGED
@@ -31,8 +31,7 @@ module KindleNotebook
|
|
31
31
|
|
32
32
|
def open_book
|
33
33
|
session.visit(KindleNotebook.configuration.url) unless session.has_selector?("p", text: title)
|
34
|
-
session.find("p", text: title).click
|
35
|
-
sleep 3 # book might take a bit to load
|
34
|
+
session.find("p", text: title, wait: 3).click
|
36
35
|
end
|
37
36
|
end
|
38
37
|
end
|
@@ -1,20 +1,64 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module KindleNotebook
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
class Client
|
5
|
+
attr_reader :session
|
6
|
+
|
7
|
+
def initialize(email: KindleNotebook.configuration.login,
|
8
|
+
password: KindleNotebook.configuration.password,
|
9
|
+
headless_mode: KindleNotebook.configuration.headless_mode,
|
10
|
+
selenium_driver: KindleNotebook.configuration.selenium_driver)
|
11
|
+
@email = email
|
12
|
+
@password = password
|
13
|
+
@headless_mode = headless_mode
|
14
|
+
@selenium_driver = selenium_driver.to_sym
|
15
|
+
@session = new_capybara_session
|
16
|
+
end
|
17
|
+
|
18
|
+
def books
|
19
|
+
@books ||= fetch_books
|
20
|
+
end
|
21
|
+
|
22
|
+
def sign_in
|
23
|
+
AmazonAuth.new(password: password, email: email).sign_in
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :email, :password, :headless_mode, :selenium_driver
|
29
|
+
|
30
|
+
def fetch_books
|
31
|
+
session.find("ul#cover").all("li").map do |element|
|
32
|
+
Book.new(author: element.find("div", id: /author-/).text,
|
33
|
+
title: element.find("div", id: /title-/).text,
|
34
|
+
asin: element.find("div", match: :first)["data-asin"])
|
8
35
|
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def new_capybara_session
|
39
|
+
chrome_driver
|
40
|
+
firefox_driver
|
41
|
+
|
42
|
+
KindleNotebook.session = Capybara::Session.new(selenium_driver)
|
43
|
+
end
|
44
|
+
|
45
|
+
def firefox_driver
|
46
|
+
Capybara.register_driver :firefox do |app|
|
47
|
+
options = Selenium::WebDriver::Firefox::Options.new
|
48
|
+
options.add_argument("--headless") if headless_mode
|
49
|
+
|
50
|
+
Capybara::Selenium::Driver.new(app, browser: :firefox, options: options)
|
51
|
+
end
|
52
|
+
end
|
9
53
|
|
10
|
-
|
54
|
+
def chrome_driver
|
55
|
+
Capybara.register_driver :chrome do |app|
|
56
|
+
options = Selenium::WebDriver::Chrome::Options.new
|
57
|
+
options.add_argument("--headless") if headless_mode
|
58
|
+
options.add_argument("--disable-gpu")
|
59
|
+
options.add_argument("--no-sandbox")
|
11
60
|
|
12
|
-
|
13
|
-
KindleNotebook.session.find("ul#cover").all("li").map do |element|
|
14
|
-
Book.new(author: element.find("div", id: /author-/).text,
|
15
|
-
title: element.find("div", id: /title-/).text,
|
16
|
-
asin: element.find("div", match: :first)["data-asin"])
|
17
|
-
end
|
61
|
+
Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
|
18
62
|
end
|
19
63
|
end
|
20
64
|
end
|
@@ -29,7 +29,8 @@ module KindleNotebook
|
|
29
29
|
|
30
30
|
# fetch all highlights (without context) from notebook
|
31
31
|
def notebook_highlights
|
32
|
-
|
32
|
+
notebook_content = session.all("div", class: "notebook-content")
|
33
|
+
content = notebook_content.any? ? notebook_content.first.all("ion-item") : []
|
33
34
|
puts "#{content.count} highlights in this book \n"
|
34
35
|
book.highlights_count = content.count
|
35
36
|
content.map { |h| parse_notebook_highlight(h) }
|
@@ -82,7 +83,7 @@ module KindleNotebook
|
|
82
83
|
end
|
83
84
|
|
84
85
|
def show_toolbar
|
85
|
-
session.first(:xpath, "//ion-header", wait:
|
86
|
+
session.first(:xpath, "//ion-header", wait: 3).hover
|
86
87
|
end
|
87
88
|
|
88
89
|
def search_highlight_context(text, page)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kindle-notebook
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bianca Vieira
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-07-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: capybara
|
@@ -103,8 +103,7 @@ files:
|
|
103
103
|
- LICENSE.txt
|
104
104
|
- README.md
|
105
105
|
- Rakefile
|
106
|
-
-
|
107
|
-
- kindle_notebook-0.2.1.gem
|
106
|
+
- kindle-notebook.gemspec
|
108
107
|
- lib/kindle-notebook.rb
|
109
108
|
- lib/kindle_notebook/amazon_auth.rb
|
110
109
|
- lib/kindle_notebook/book.rb
|
data/kindle_notebook-0.2.0.gem
DELETED
Binary file
|
data/kindle_notebook-0.2.1.gem
DELETED
Binary file
|