foxit 0.1.1 → 0.1.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 541b370e85c872627d4bff2419a6af1d8ce922c8e19363218aad0f6642b435ab
4
- data.tar.gz: 74738a7174d332d718573188510a6e4744f8b08b7cb66735ae758fadb65dfd1c
3
+ metadata.gz: 4f2ddc5e34db607cabc25cd0df88a4a1830df59757d2021fd75ef414d6cfc9bd
4
+ data.tar.gz: 7689130ad6eea5df3f7f7b5a49df55e548890e4513223fa98cfc65b078718f3c
5
5
  SHA512:
6
- metadata.gz: 4dcfdbcf7d13ec79d4501298fe49379b07fff9736829a42f01ecaee043aa0ccfde9a1bd6861c8ea63bb0824cf6f134a1ec81e9d5f83956388a86420e4d872ca9
7
- data.tar.gz: e597208dcabad4affd0ff242bbcec7cddc7ae85afb0f499193d85b82dbf9885a0cb32b2719795907d60608c21c55671ea5daf32c3356ccc4e24b0a2c0f18f974
6
+ metadata.gz: 9912bb8e912a1b41ee8150c341e4cb75718466058a78193c48835d2cf8d3b2470941015a3820a501daaa5809d906537c36518917cb7d5383f2fafaf922090255
7
+ data.tar.gz: 11fe6338525040504c52537e7dfe565bcbb29a07ea8551687a3721deb5d88fb4f3078b7c6c822ff19dd85815eecc434f21828a6dcde1f40bb9aed3737c8a8f8d
data/.gitignore CHANGED
@@ -3,4 +3,5 @@
3
3
  /scratch
4
4
  /notebooks
5
5
  /examples
6
- /.vscode
6
+ /.vscode
7
+ /archive
data/README.md CHANGED
@@ -13,22 +13,38 @@ gem install foxit
13
13
  A few quick examples are detailed below:
14
14
 
15
15
  ### Retrieving Data
16
- Get an anime item by id.
16
+ Get an anime item by id or slug.
17
17
  ```ruby
18
18
  api = Foxit::API.new()
19
19
  result = api.get_anime_by_id(1)
20
+ result = api.get_anime_by_slug('cowboy-bebop')
21
+ ```
22
+ The slug is basically the hyphen separated version of the name with the special characters removed. When you click on a anime item in kitsu it will be at the end of the url. This returns the `Anime` object; however, the full json response can be obtained as per below:
23
+ ```ruby
24
+ result = api.get_anime_by_id(1, :json)
20
25
  ```
21
26
 
22
- This returns the full json response; however, an object based result can be returned as per the following (planned to be returned as default)
27
+ Similarly, getting a users library. Returns a list of `LibraryItem` objects.
23
28
  ```ruby
24
- item = Anime.new(result['data'])
29
+ result = api.get_user_library_by_id(1)
25
30
  ```
26
31
 
27
- Similarly, getting a users library. This returns a list of entries from the `'data'` attribute of the json returned.
32
+ This returns a list of entries (hash format) from the `'data'` attribute of the json returned.
28
33
  ```ruby
29
34
  result = api.get_library_by_id(1)
30
35
  ```
31
36
 
37
+ Examples of getting a batch of anime results:
38
+ ```ruby
39
+ result = api.batch_get_anime([1, 4, 8, 25])
40
+ ```
41
+
42
+ Similarly, user library examples below. Note: the library batch results are returned as a flat array (filter on user_id to split out).
43
+ ```ruby
44
+ result = api.batch_get_libraries(1..10)
45
+ result = api.batch_get_libraries([1, 2, 3, 5])
46
+ ```
47
+
32
48
 
33
49
  ### Storing Data with MongoDB
34
50
  If you don't have mongodb installed you can download the free community version from [here][mongodb]. Once installed, you need to start the service via terminal:
@@ -6,7 +6,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "foxit"
8
8
  # spec.version = Foxit::VERSION
9
- spec.version = "0.1.1"
9
+ spec.version = "0.1.3"
10
10
  spec.authors = ["Lachlan Taylor"]
11
11
  spec.email = ["lachlanbtaylor@gmail.com"]
12
12
 
@@ -1,5 +1,6 @@
1
1
  require "foxit/objects"
2
2
  require "foxit/helpers"
3
+ require "foxit/url_builder"
3
4
 
4
5
 
5
6
  module Foxit
@@ -1,37 +1,23 @@
1
1
  require_relative 'objects'
2
+ require_relative 'helpers'
3
+ require_relative 'url_builder'
2
4
 
3
5
  require 'net/http'
4
6
  require 'json'
5
- require 'addressable/uri'
6
7
 
7
8
 
8
9
 
9
10
  module Foxit
10
11
 
11
- class API
12
+ # TODO: probably split out library and anime methods
13
+ class API < Helpers
12
14
 
13
- def initialize
14
- @root = "https://kitsu.io/api/edge/"
15
- end
16
-
17
-
18
- def build_library_url id, type='Anime', status='completed', limit=500
19
- uri = Addressable::URI.parse("#{@root}library-entries")
20
-
21
- uri_query = {
22
- "filter[user_id]" => id,
23
- "filter[media_type]" => type,
24
- "filter[status]" => status,
25
- "page[limit]" => limit
26
- }
27
- uri.query_values = uri_query
28
-
29
- uri.to_s
30
- end
31
-
32
-
33
- def build_media_url entry_id
34
- "#{@root}/library-entries/#{entry_id}/relationships/media"
15
+ attr_reader :urlbuilder
16
+ attr_accessor :max_threads
17
+
18
+ def initialize max_threads=200
19
+ @max_threads = max_threads
20
+ @urlbuilder = URLBuilder.new()
35
21
  end
36
22
 
37
23
 
@@ -41,14 +27,14 @@ module Foxit
41
27
  end
42
28
 
43
29
 
44
- def get_library_by_url url, entries=[]
30
+ def _get_library_by_url url, entries=[]
45
31
 
46
32
  result = self.get_result(url)
47
33
  entries += result['data']
48
34
 
49
35
  if result['links'].key?('next')
50
36
  # recursion to retrieve additional results that have ben paginated
51
- result = self.get_library_by_url(result['links']['next'], entries)
37
+ result = self._get_library_by_url(result['links']['next'], entries)
52
38
  else
53
39
  return entries
54
40
  end
@@ -56,8 +42,8 @@ module Foxit
56
42
 
57
43
 
58
44
  def get_library_by_id user_id
59
- url = self.build_library_url(user_id)
60
- self.get_library_by_url(url)
45
+ url = @urlbuilder.library(user_id)
46
+ self._get_library_by_url(url)
61
47
  end
62
48
 
63
49
 
@@ -67,17 +53,16 @@ module Foxit
67
53
  @get_media_relationship_by_id ||= {}
68
54
  return @get_media_relationship_by_id[entry_id] if @get_media_relationship_by_id.key?(entry_id)
69
55
 
70
- url = self.build_media_url(entry_id)
56
+ url = @urlbuilder.media(entry_id)
71
57
  self.get_result(url)
72
58
  end
73
59
 
74
60
 
75
- def batch_get_results ids, fn, max_threads
61
+ def batch_get_results ids, fn
76
62
  """
77
63
  ids: ids of results returned: user_id | library_entry_id in this case.
78
64
  fn: function name to use to return results (need to use symbol method name)
79
65
  e.g. :get_result
80
- max_threads: maximum number of active threads.
81
66
  """
82
67
 
83
68
  results = {}
@@ -85,7 +70,7 @@ module Foxit
85
70
 
86
71
  ids.each do |id|
87
72
 
88
- if Thread.list.count % max_threads != 0
73
+ if Thread.list.count % @max_threads != 0
89
74
  thread = Thread.new do
90
75
  # adding lock slows down considerably shouldn't matter as results are written to hash?
91
76
  results[id] = send(fn, id)
@@ -108,56 +93,101 @@ module Foxit
108
93
  results
109
94
  end
110
95
 
111
- # TODO: should probably assign to a @variable
112
- def batch_get_libraries user_ids, max_threads=200
96
+
97
+ def batch_get_libraries user_ids
113
98
 
114
99
  all_library_entries = []
115
- user_libraries = self.batch_get_results(user_ids, :get_library_by_id, max_threads)
100
+ user_libraries = self.batch_get_results(user_ids, :get_library_by_id)
116
101
 
117
102
  user_libraries.each do |user_id, library|
118
-
119
- media_ids = []
120
- library.map { |entry| media_ids << entry['id'] }
121
- media_results = self.batch_get_results(media_ids, :get_media_relationship_by_id, max_threads)
122
-
123
- library.each do |entry|
124
- all_library_entries << LibraryItem.new(user_id, entry, media_results[entry['id']])
125
- end
126
-
103
+ all_library_entries += self._create_library_items(user_id, library)
127
104
  end
128
105
 
129
106
  all_library_entries
130
107
  end
131
-
108
+
109
+
110
+ def _create_library_items user_id, library
111
+
112
+ # get media_ids from record_ids (not in same response, additional request required)
113
+ record_ids = []
114
+ library.map { |entry| record_ids << entry['id'] }
115
+ media_results = self.batch_get_results(record_ids, :get_media_relationship_by_id)
116
+
117
+ library_entries = []
118
+ library.each do |entry|
119
+ library_entries << LibraryItem.new(user_id, entry, media_results[entry['id']])
120
+ end
121
+
122
+ library_entries
123
+ end
124
+
132
125
 
133
- def get_user_library
134
- # TODO: return user library using single id call to batch_get_library
126
+ def get_user_library_by_id user_id
127
+ library = self.get_library_by_id(user_id)
128
+ self._create_library_items(user_id, library)
135
129
  end
136
130
 
137
131
 
138
- def batch_get_libraries_docs user_ids, max_threads=200
139
- all_library_entries = self.batch_get_libraries(user_ids, max_threads)
132
+ def batch_get_libraries_docs user_ids
133
+ all_library_entries = self.batch_get_libraries(user_ids)
140
134
 
141
135
  docs = []
142
136
  all_library_entries.map { |entry| docs << entry.to_hash }
143
137
 
144
138
  docs
145
139
  end
146
-
147
-
148
- def build_anime_url id
149
- "#{@root}/anime/#{id}"
140
+
141
+
142
+ def _get_anime_by_attr filter_attr, filter_value, rtype=:object
143
+
144
+ # TODO: this is a bit of a mess
145
+
146
+ case filter_attr
147
+ when :id
148
+ url = @urlbuilder.anime_by_id(filter_value)
149
+ when :slug
150
+ url = @urlbuilder.anime_by_slug(filter_value)
151
+ else
152
+ raise ArgumentError.new("filter_attr argument (1st) not in {:id, :slug}")
153
+ end
154
+
155
+ result = self.get_result(url)
156
+
157
+ case rtype
158
+ when :json
159
+ return result
160
+ when :object
161
+ case filter_attr
162
+ when :id
163
+ return Anime.new(result['data'])
164
+ when :slug
165
+ # filtering by slug results in the 'data' attribute to be an array
166
+ return Anime.new(result['data'][0])
167
+ end
168
+ else
169
+ raise ArgumentError.new("rtype not :object or :json")
170
+ end
150
171
  end
151
-
152
-
153
- def get_anime_by_id id
154
- url = build_anime_url(id)
155
- self.get_result(url)
172
+
173
+
174
+ def get_anime_by_id id, rtype=:object
175
+ self._get_anime_by_attr(:id, id, rtype)
156
176
  end
157
-
158
-
159
- def batch_get_anime anime_ids, max_threads=200
160
- results = self.batch_get_results(anime_ids, :get_anime_by_id, max_threads)
177
+
178
+
179
+ def get_anime_by_slug slug, rtype=:object
180
+ self._get_anime_by_attr(:slug, slug, rtype)
181
+ end
182
+
183
+
184
+ def _get_anime_by_id_json id
185
+ self._get_anime_by_attr(:id, id, :json)
186
+ end
187
+
188
+
189
+ def batch_get_anime anime_ids
190
+ results = self.batch_get_results(anime_ids, :_get_anime_by_id_json)
161
191
 
162
192
  anime_items = []
163
193
  results.each do |id, result|
@@ -169,8 +199,9 @@ module Foxit
169
199
  anime_items
170
200
  end
171
201
 
172
- def get_anime_documents anime_ids, max_threads=200
173
- anime_items = self.batch_get_anime(anime_ids, max_threads)
202
+
203
+ def get_anime_documents anime_ids
204
+ anime_items = self.batch_get_anime(anime_ids)
174
205
  self.objects_to_hash(anime_items)
175
206
  end
176
207
 
@@ -0,0 +1,43 @@
1
+ require 'addressable/uri'
2
+
3
+
4
+
5
+ class URLBuilder
6
+
7
+ attr_reader :root
8
+
9
+ def initialize
10
+ @root = "https://kitsu.io/api/edge/"
11
+ end
12
+
13
+
14
+ def media entry_id
15
+ "#{@root}/library-entries/#{entry_id}/relationships/media"
16
+ end
17
+
18
+
19
+ def library id, type='Anime', status='completed', limit=500
20
+ uri = Addressable::URI.parse("#{@root}library-entries")
21
+
22
+ uri_query = {
23
+ "filter[user_id]" => id,
24
+ "filter[media_type]" => type,
25
+ "filter[status]" => status,
26
+ "page[limit]" => limit
27
+ }
28
+ uri.query_values = uri_query
29
+
30
+ uri.to_s
31
+ end
32
+
33
+
34
+ def anime_by_id id
35
+ "#{@root}/anime/#{id}"
36
+ end
37
+
38
+
39
+ def anime_by_slug slug
40
+ "#{@root}/anime?filter[slug]=#{slug}"
41
+ end
42
+
43
+ end
@@ -0,0 +1,44 @@
1
+ require "test/unit"
2
+
3
+ require_relative '../lib/foxit/api'
4
+
5
+
6
+
7
+ class TestGetAnimeResponses < Test::Unit::TestCase
8
+
9
+ def setup
10
+ @api = Foxit::API.new()
11
+ @slug = 'cowboy-bebop'
12
+ end
13
+
14
+ def test__get_anime_by_attr_id_json
15
+ result = @api._get_anime_by_attr(:id, 1, :json)
16
+ assert_equal(@slug, result['data']['attributes']['slug'])
17
+ end
18
+
19
+ def test__get_anime_by_attr_id_object
20
+ result = @api._get_anime_by_attr(:id, 1, :object)
21
+ assert_equal(@slug, result.slug)
22
+ end
23
+
24
+ def test__get_anime_by_attr_slug_json
25
+ result = @api._get_anime_by_attr(:slug, @slug, :json)
26
+ assert_equal(@slug, result['data'][0]['attributes']['slug'])
27
+ end
28
+
29
+ def test__get_anime_by_attr_slug_object
30
+ result = @api._get_anime_by_attr(:slug, @slug, :object)
31
+ assert_equal(@slug, result.slug)
32
+ end
33
+
34
+ def test_get_anime_by_id_base
35
+ result = @api.get_anime_by_id(1)
36
+ assert_equal(@slug, result.slug)
37
+ end
38
+
39
+ def test_get_anime_by_slug_base
40
+ result = @api.get_anime_by_slug(@slug)
41
+ assert_equal(@slug, result.slug)
42
+ end
43
+
44
+ end
@@ -0,0 +1,32 @@
1
+ require "test/unit"
2
+
3
+ require_relative '../lib/foxit/api'
4
+
5
+
6
+
7
+ class TestGetLibraryResults < Test::Unit::TestCase
8
+
9
+ def setup
10
+ @api = Foxit::API.new()
11
+ @user_id = 1
12
+ end
13
+
14
+ def test_get_library_by_id
15
+ result = @api.get_library_by_id(@user_id)
16
+ assert_kind_of(Hash, result[0], 'result should be an array of Hash objects')
17
+ assert(result.length > 10, 'user library should not be empty') # user 1 library is 35 'complete' items
18
+ end
19
+
20
+ def test_get_user_library_by_id
21
+ result = @api.get_user_library_by_id(@user_id)
22
+ assert_kind_of(LibraryItem, result[0], 'result should be an array of LibraryItem objects')
23
+ assert(result.length > 10, 'user library should not be empty')
24
+ end
25
+
26
+ def test_batch_get_libraries
27
+ result = @api.batch_get_libraries(1..2)
28
+ assert_kind_of(LibraryItem, result[0], 'result should be an array of LibraryItem objects')
29
+ assert(result.length > 40, 'user library should not be empty')
30
+ end
31
+
32
+ end
@@ -0,0 +1,4 @@
1
+ require "test/unit"
2
+
3
+ require_relative 'tc_get_anime_results'
4
+ require_relative 'tc_get_library_results'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foxit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lachlan Taylor
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-07-26 00:00:00.000000000 Z
11
+ date: 2018-08-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -87,6 +87,10 @@ files:
87
87
  - lib/foxit/etl.rb
88
88
  - lib/foxit/helpers.rb
89
89
  - lib/foxit/objects.rb
90
+ - lib/foxit/url_builder.rb
91
+ - tests/tc_get_anime_results.rb
92
+ - tests/tc_get_library_results.rb
93
+ - tests/ts_all.rb
90
94
  homepage: https://github.com/rokkuran/foxit
91
95
  licenses:
92
96
  - MIT