kindle-highlights 0.0.8 → 1.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c7c203ab1e9aad56bd379b3e6b5cc664136f2c18
4
+ data.tar.gz: 8182d4dfbfce7296a66785a2b595929cc6c18a3a
5
+ SHA512:
6
+ metadata.gz: 7414e1b4930c3aaaec740d37815749aa1e4f6ce87852d9051059688d1e7b978586cb5ee2694ed212ee0fb4f0c3a27741d07968e5a3c807cce53dd752c165a505
7
+ data.tar.gz: aef2a7e0ea42a2c40c02abc42d4af20329645e1c5f9ca137dc2a57818205762f18226826a2bb8cb86f128fd767f12eb55230fc24d00a3360c6ecca71a43be1aa
@@ -4,7 +4,7 @@ require 'json'
4
4
  require 'kindle_highlights/client'
5
5
 
6
6
  module KindleHighlights
7
-
8
7
  KINDLE_LOGIN_PAGE = "http://kindle.amazon.com/login"
9
8
  SIGNIN_FORM_IDENTIFIER = "signIn"
10
- end
9
+ BATCH_SIZE = 200
10
+ end
@@ -1,50 +1,93 @@
1
1
  module KindleHighlights
2
2
  class Client
3
- attr_reader :books
4
-
5
- def initialize(email_address, password)
6
- @email_address = email_address
7
- @password = password
8
-
9
- setup_mechanize_agent
10
- load_books_from_kindle_account
3
+ class CaptchaError < StandardError; end
4
+
5
+ attr_writer :mechanize_agent
6
+ attr_accessor :kindle_logged_in_page
7
+
8
+ def initialize(email_address:, password:, mechanize_options: {})
9
+ @email_address = email_address
10
+ @password = password
11
+ @mechanize_options = mechanize_options
12
+ end
13
+
14
+ def books
15
+ @books ||= load_books_from_kindle_account
11
16
  end
12
-
17
+
13
18
  def highlights_for(asin)
14
- highlights = @mechanize_agent.get("https://kindle.amazon.com/kcw/highlights?asin=#{asin}&cursor=0&count=1000")
15
- json = JSON.parse(highlights.body)
16
- json["items"]
19
+ conditionally_sign_in_to_amazon
20
+
21
+ cursor = 0
22
+ highlights = []
23
+
24
+ loop do
25
+ # This endpoint includes a `hasMore` field. Unfortunately at the time of this writing is always `false`.
26
+ page = mechanize_agent.get("https://kindle.amazon.com/kcw/highlights?asin=#{asin}&cursor=#{cursor}&count=#{BATCH_SIZE}")
27
+ items = JSON.parse(page.body).fetch("items", [])
28
+
29
+ break unless items.any?
30
+
31
+ highlights.concat(items)
32
+ cursor += BATCH_SIZE
33
+ end
34
+ highlights
17
35
  end
18
-
36
+
19
37
  private
20
-
38
+
39
+ attr_accessor :email_address, :password, :mechanize_options
40
+
41
+ def conditionally_sign_in_to_amazon
42
+ if @kindle_logged_in_page.nil?
43
+ signin_page = mechanize_agent.get(KINDLE_LOGIN_PAGE)
44
+ signin_form = signin_page.form(SIGNIN_FORM_IDENTIFIER)
45
+ signin_form.email = email_address
46
+ signin_form.password = password
47
+ post_signin_page = mechanize_agent.submit(signin_form)
48
+
49
+ if post_signin_page.search("#ap_captcha_img").any?
50
+ resolution_url = post_signin_page.link_with(text: /See a new challenge/).resolved_uri.to_s
51
+ raise CaptchaError, "Received a CAPTCHA while attempting to sign in to your Amazon account. You will need to resolve this manually at #{resolution_url}"
52
+ else
53
+ @kindle_logged_in_page = post_signin_page
54
+ end
55
+ end
56
+ end
57
+
21
58
  def load_books_from_kindle_account
22
- @books = Hash.new
23
- signin_page = @mechanize_agent.get(KINDLE_LOGIN_PAGE)
24
-
25
- signin_form = signin_page.form(SIGNIN_FORM_IDENTIFIER)
26
- signin_form.email = @email_address
27
- signin_form.password = @password
28
-
29
- kindle_logged_in_page = @mechanize_agent.submit(signin_form)
30
- highlights_page = @mechanize_agent.click(kindle_logged_in_page.link_with(:text => /Your Books/))
59
+ conditionally_sign_in_to_amazon
60
+
61
+ books = {}
62
+ highlights_page = mechanize_agent.click(kindle_logged_in_page.link_with(text: /Your Books/))
31
63
 
32
64
  loop do
33
- books = highlights_page.search(".//td[@class='titleAndAuthor']")
34
- books.each do |book|
35
- asin = book.search("a").first.attributes["href"].value.split("/").last
36
- title = book.search("a").first.inner_html
37
- @books[asin] = title
65
+ highlights_page.search(".//td[@class='titleAndAuthor']").each do |book|
66
+ asin_and_title_element = book.search("a").first
67
+ asin = asin_and_title_element.attributes.fetch("href").value.split("/").last
68
+ title = asin_and_title_element.inner_html
69
+ books[asin] = title
38
70
  end
71
+
39
72
  break if highlights_page.link_with(text: /Next/).nil?
40
- highlights_page = @mechanize_agent.click(highlights_page.link_with(text: /Next/))
73
+ highlights_page = mechanize_agent.click(highlights_page.link_with(text: /Next/))
41
74
  end
75
+ books
76
+ end
77
+
78
+ def mechanize_agent
79
+ @mechanize_agent ||= initialize_mechanize_agent
42
80
  end
43
-
44
- def setup_mechanize_agent
45
- @mechanize_agent = Mechanize.new
46
- @mechanize_agent.user_agent_alias = 'Windows Mozilla'
47
- @mechanize_agent.agent.http.verify_mode = OpenSSL::SSL::VERIFY_NONE
81
+
82
+ def initialize_mechanize_agent
83
+ mechanize_agent = Mechanize.new
84
+ mechanize_agent.user_agent_alias = 'Windows Mozilla'
85
+ mechanize_agent.agent.http.verify_mode = OpenSSL::SSL::VERIFY_NONE
86
+
87
+ mechanize_options.each do |mech_attr, value|
88
+ mechanize_agent.send("#{mech_attr}=", value)
89
+ end
90
+ mechanize_agent
48
91
  end
49
92
  end
50
- end
93
+ end
metadata CHANGED
@@ -1,32 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kindle-highlights
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
5
- prerelease:
4
+ version: 1.0.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Eric Farkas
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-08-21 00:00:00.000000000 Z
11
+ date: 2016-03-10 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: mechanize
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - ">="
20
18
  - !ruby/object:Gem::Version
21
19
  version: 2.7.2
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - ">="
28
25
  - !ruby/object:Gem::Version
29
26
  version: 2.7.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '5.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '5.0'
30
69
  description: Until there is a Kindle API, this will suffice.
31
70
  email: eric@prudentiadigital.com
32
71
  executables: []
@@ -36,28 +75,28 @@ files:
36
75
  - lib/kindle_highlights.rb
37
76
  - lib/kindle_highlights/client.rb
38
77
  homepage: https://github.com/speric/kindle-highlights
39
- licenses: []
78
+ licenses:
79
+ - MIT
80
+ metadata: {}
40
81
  post_install_message:
41
82
  rdoc_options: []
42
83
  require_paths:
43
84
  - lib
44
85
  required_ruby_version: !ruby/object:Gem::Requirement
45
- none: false
46
86
  requirements:
47
- - - ! '>='
87
+ - - ">="
48
88
  - !ruby/object:Gem::Version
49
- version: '0'
89
+ version: 2.1.0
50
90
  required_rubygems_version: !ruby/object:Gem::Requirement
51
- none: false
52
91
  requirements:
53
- - - ! '>='
92
+ - - ">="
54
93
  - !ruby/object:Gem::Version
55
94
  version: '0'
56
95
  requirements: []
57
96
  rubyforge_project:
58
- rubygems_version: 1.8.22
97
+ rubygems_version: 2.2.3
59
98
  signing_key:
60
- specification_version: 3
99
+ specification_version: 4
61
100
  summary: Kindle highlights
62
101
  test_files: []
63
102
  has_rdoc: