livefyre 1.3.2 → 2.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.
Files changed (46) hide show
  1. checksums.yaml +5 -13
  2. data/.gitignore +3 -6
  3. data/CHANGELOG +10 -0
  4. data/README.md +3 -66
  5. data/circle.yml +10 -0
  6. data/lib/livefyre.rb +1 -1
  7. data/lib/livefyre/api/domain.rb +15 -0
  8. data/lib/livefyre/api/personalized_stream.rb +79 -72
  9. data/lib/livefyre/core/collection.rb +93 -0
  10. data/lib/livefyre/core/network.rb +61 -56
  11. data/lib/livefyre/core/site.rb +34 -82
  12. data/lib/livefyre/cursor/timeline_cursor.rb +45 -0
  13. data/lib/livefyre/{entity → dto}/subscription.rb +12 -14
  14. data/lib/livefyre/{entity → dto}/topic.rb +16 -13
  15. data/lib/livefyre/exceptions/api_exception.rb +29 -0
  16. data/lib/livefyre/exceptions/livefyre_exception.rb +9 -0
  17. data/lib/livefyre/factory/cursor_factory.rb +4 -4
  18. data/lib/livefyre/model/collection_data.rb +30 -0
  19. data/lib/livefyre/model/cursor_data.rb +17 -0
  20. data/lib/livefyre/model/network_data.rb +10 -0
  21. data/lib/livefyre/model/site_data.rb +10 -0
  22. data/lib/livefyre/type/collection_type.rb +11 -0
  23. data/lib/livefyre/type/subscription_type.rb +5 -0
  24. data/lib/livefyre/utils/livefyre_util.rb +24 -0
  25. data/lib/livefyre/validator/collection_validator.rb +33 -0
  26. data/lib/livefyre/validator/cursor_validator.rb +15 -0
  27. data/lib/livefyre/validator/network_validator.rb +19 -0
  28. data/lib/livefyre/validator/site_validator.rb +14 -0
  29. data/lib/livefyre/version.rb +1 -1
  30. data/livefyre.gemspec +15 -12
  31. data/spec/livefyre/api/domain_spec.rb +40 -0
  32. data/spec/livefyre/api/personalized_stream_spec.rb +54 -37
  33. data/spec/livefyre/core/collection_spec.rb +90 -0
  34. data/spec/livefyre/core/network_spec.rb +32 -6
  35. data/spec/livefyre/core/site_spec.rb +24 -62
  36. data/spec/livefyre/cursor/timeline_cursor_spec.rb +25 -0
  37. data/spec/livefyre/dto/subscription_spec.rb +27 -0
  38. data/spec/livefyre/dto/topic_spec.rb +35 -0
  39. data/spec/livefyre/factory/cursor_factory_spec.rb +29 -0
  40. data/spec/livefyre/utils/utils_spec.rb +30 -0
  41. data/spec/spec_helper.rb +34 -0
  42. metadata +134 -72
  43. data/.idea/misc.xml +0 -5
  44. data/.idea/modules.xml +0 -9
  45. data/lib/livefyre/entity/timeline_cursor.rb +0 -41
  46. data/spec/livefyre/test_spec.rb +0 -7
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MTMyOTJlNDUxZTNiZjI0MWJhNjVkNTZlODFkYmRiZjc5NmIxN2EyYg==
5
- data.tar.gz: !binary |-
6
- MjdiM2JmM2VkZDk1NDNiOGM3MjBhMTMwNGNjZTMxNjM0NzdiYmE3Mw==
2
+ SHA1:
3
+ metadata.gz: f06aa9e52cc7fc5fda39f58fa711a26bcf6e8a73
4
+ data.tar.gz: 7ea049454d503278566baab91602b9dbd7aecec6
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- N2U1OGQzOTc1MmQyOTg2Nzc5YmYwMWNmZjQ3MzlmODY2NDE0OGMyOGQzNzg5
10
- OTA4ZDA4YTU5NWRhMjk5OWZiNGU0ZDEyNzBhMjM5NjI0ZjQ4MDZlY2ZjYTQ4
11
- NWI3MGViMjcxMzgzOTUyZTBhMDUxODg5NWI0N2YwZDQzYWQ0MDg=
12
- data.tar.gz: !binary |-
13
- OWY5Y2ZjNjI2YTRjMGZhN2M3ZTk4NTVkZTdlMzM4YmE3ZmQwOGRmZGI5Yzc4
14
- NjQ5MmQ4MmFkMGY5Y2U5NjEzNTkwODEzNmJlMWVhNDBkNDFlMDlmYjFjOWIw
15
- MmRiMzBhZjRhOWNlM2U4NjllOTYzYTE0Y2RmYjcyOGY1OWYwOTU=
6
+ metadata.gz: 01772d1963e0b7f0eaf7fc3f5fd125f87b707e29c9ee56fa81796428dd1d98901a30e501202cd1a5e8eb349d2c9803da4a914a40d49077ee2e59d2984ac95461
7
+ data.tar.gz: 257d7ff4facaa56fcf536488fe334c6972b3160c8c9b457f8e285eed1e537b108ab461258c045f3e881dc6fd03b096fb789595977c056ab5462a4e1558f29305
data/.gitignore CHANGED
@@ -15,9 +15,6 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
-
19
- .idea/livefyre-ruby-utils.iml
20
-
21
- .idea/workspace.xml
22
-
23
- .idea/livefyre-ruby-utils.iml
18
+ .idea
19
+ *.iml
20
+ test.yml
data/CHANGELOG CHANGED
@@ -1,3 +1,13 @@
1
+ === 2.0.0 2014-10-18
2
+
3
+ * Added many more tests and test config.
4
+ * Added coveralls for test coverage.
5
+ * Refactored Collection related methods into its own class.
6
+ * Restructured the library.
7
+ * Refactored many parts of the library and updated its dependencies.
8
+ * Added requirements to have fyre.co at end of network name.
9
+ * Made user auth check allow dash, underscore, and dots.
10
+
1
11
  === 1.3.2 2014-08-12
2
12
 
3
13
  * Added SSL toggle for all API requests.
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Livefyre Ruby Utility Classes
2
2
  [![Gem Version](https://badge.fury.io/rb/livefyre.png)](http://badge.fury.io/rb/livefyre)
3
+ [![Circle CI](https://circleci.com/gh/Livefyre/livefyre-ruby-utils.png?style=badge)](https://circleci.com/gh/Livefyre/livefyre-ruby-utils)
4
+ [![Coverage Status](https://coveralls.io/repos/Livefyre/livefyre-ruby-utils/badge.png)](https://coveralls.io/r/Livefyre/livefyre-ruby-utils)
3
5
 
4
6
  Livefyre's official library for common server-side tasks necessary for getting Livefyre apps (comments, reviews, etc.) working on your website.
5
7
 
@@ -13,72 +15,7 @@ Or install it yourself:
13
15
 
14
16
  $ gem install livefyre
15
17
 
16
- ## Usage
17
-
18
- Instantiating a network object:
19
-
20
- ```ruby
21
- network = Livefyre.get_network('network_name', 'network_key')
22
- ```
23
-
24
- Building a Livefyre token:
25
-
26
- ```ruby
27
- network.build_livefyre_token
28
- ```
29
-
30
- Building a user auth token:
31
-
32
- ```ruby
33
- network.build_user_auth_token('user_id', 'display_name', expires)
34
- ```
35
-
36
- To validate a Livefyre token:
37
-
38
- ```ruby
39
- network.validate_livefyre_token('lf_token')
40
- ```
41
-
42
- To send Livefyre a user sync url and then have Livefyre pull user data from that url:
43
-
44
- ```ruby
45
- network.set_user_sync_url('url_template')
46
- network.sync_user('user_id')
47
- ```
48
-
49
- Instantiating a site object:
50
-
51
- ```ruby
52
- site = network.get_site('site_id', 'site_key')
53
- ```
54
-
55
- Building a collection meta token:
56
- *The {options} argument is optional.*
57
-
58
- ```ruby
59
- site.build_collection_meta_token('title', 'article_id', 'url', {options})
60
- ```
61
-
62
- Building a checksum:
63
- *The 'tags' argument is optional.*
64
-
65
- ```ruby
66
- site.build_checksum('title', 'url', 'tags')
67
- ```
68
-
69
- To retrieve content collection data:
70
-
71
- ```ruby
72
- site.get_collection_content('article_id')
73
- ```
74
-
75
- To get a content collection's id:
76
-
77
- ```ruby
78
- site.get_collection_id('article_id')
79
- ```
80
-
81
- ## Additional Documentation
18
+ ## Documentation
82
19
 
83
20
  Located [here](http://answers.livefyre.com/developers/libraries).
84
21
 
data/circle.yml ADDED
@@ -0,0 +1,10 @@
1
+ dependencies:
2
+ pre:
3
+ - gem install bundler #temporary as circle uses 1.6.5 at the moment
4
+ test:
5
+ override:
6
+ - bundle exec rspec spec
7
+
8
+ machine:
9
+ timezone:
10
+ America/Los_Angeles
data/lib/livefyre.rb CHANGED
@@ -2,6 +2,6 @@ require 'livefyre/core/network'
2
2
 
3
3
  module Livefyre
4
4
  def self.get_network(network_name, network_key)
5
- Network.new(network_name, network_key)
5
+ Network.init(network_name, network_key)
6
6
  end
7
7
  end
@@ -0,0 +1,15 @@
1
+ require 'livefyre/utils/livefyre_util'
2
+
3
+ module Livefyre
4
+ class Domain
5
+ def self.quill(core)
6
+ network = LivefyreUtil::get_network_from_core(core)
7
+ network.ssl ? "https://#{network.network_name}.quill.fyre.co" : "http://quill.#{network.network_name}.fyre.co"
8
+ end
9
+
10
+ def self.bootstrap(core)
11
+ network = LivefyreUtil::get_network_from_core(core)
12
+ network.ssl ? "https://#{network.network_name}.bootstrap.fyre.co" : "http://bootstrap.#{network.network_name}.fyre.co"
13
+ end
14
+ end
15
+ end
@@ -1,11 +1,13 @@
1
1
  require 'json'
2
2
  require 'jwt'
3
3
  require 'rest-client'
4
- require 'addressable/uri'
5
4
 
6
- require 'livefyre/entity/topic'
7
- require 'livefyre/entity/subscription'
8
5
  require 'livefyre/api/domain'
6
+ require 'livefyre/dto/topic'
7
+ require 'livefyre/dto/subscription'
8
+ require 'livefyre/exceptions/livefyre_exception'
9
+ require 'livefyre/type/subscription_type'
10
+ require 'livefyre/utils/livefyre_util'
9
11
 
10
12
  module Livefyre
11
13
  class PersonalizedStream
@@ -13,8 +15,8 @@ module Livefyre
13
15
  def self.get_topic(core, topic_id)
14
16
  url = self.base_url(core) + self.topic_path(core, topic_id)
15
17
 
16
- response = RestClient.get(url, self.get_headers(core))
17
- data = JSON.parse(response)['data']
18
+ response = RestClient.get(url, self.get_headers(core)){|response, request, result| response }
19
+ data = self.analyze_response(response)
18
20
 
19
21
  Topic::serialize_from_json(data['topic'])
20
22
  end
@@ -32,8 +34,8 @@ module Livefyre
32
34
  url = self.base_url(core) + self.multiple_topic_path(core)
33
35
  url += "?limit=#{limit}&offset=#{offset}"
34
36
 
35
- response = RestClient.get(url, self.get_headers(core))
36
- data = JSON.parse(response)['data']
37
+ response = RestClient.get(url, self.get_headers(core)){|response, request, result| response }
38
+ data = self.analyze_response(response)
37
39
 
38
40
  topics = []
39
41
  data['topics'].each do |topic|
@@ -59,11 +61,11 @@ module Livefyre
59
61
 
60
62
  topics_json = []
61
63
  topics.each do |topic|
62
- topics_json << topic.to_dict
64
+ topics_json << topic.to_hash
63
65
  end
64
66
 
65
- response = RestClient.post(url, {topics: topics_json}.to_json, headers)
66
- JSON.parse(response)['data']
67
+ response = RestClient.post(url, { :topics => topics_json }.to_json, headers){|response, request, result| response }
68
+ self.analyze_response(response)
67
69
 
68
70
  return topics
69
71
  end
@@ -72,66 +74,66 @@ module Livefyre
72
74
  url = self.base_url(core) + self.multiple_topic_path(core)
73
75
  headers = self.get_headers(core)
74
76
  headers[:content_type] = :json
75
- form = {delete: self.get_ids(topics)}
77
+ form = { :delete => self.get_ids(topics) }
76
78
 
77
- response = RestClient.patch(url, form.to_json, headers)
78
- data = JSON.parse(response)['data']
79
+ response = RestClient.patch(url, form.to_json, headers){|response, request, result| response }
80
+ data = self.analyze_response(response)
79
81
 
80
82
  data.has_key?('deleted') ? data['deleted'] : 0
81
83
  end
82
84
 
83
85
  # Collection Topic API
84
- def self.get_collection_topics(site, collection_id)
85
- url = self.base_url(site) + self.collection_topics_path(site, collection_id)
86
+ def self.get_collection_topics(collection)
87
+ url = self.base_url(collection) + self.multiple_topic_path(collection)
86
88
 
87
- response = RestClient.get(url, self.get_headers(site))
88
- data = JSON.parse(response)['data']
89
+ response = RestClient.get(url, self.get_headers(collection)){|response, request, result| response }
90
+ data = self.analyze_response(response)
89
91
 
90
92
  data.has_key?('topicIds') ? data['topicIds'] : []
91
93
  end
92
94
 
93
- def self.add_collection_topics(site, collection_id, topics)
94
- url = self.base_url(site) + self.collection_topics_path(site, collection_id)
95
- headers = self.get_headers(site)
95
+ def self.add_collection_topics(collection, topics)
96
+ url = self.base_url(collection) + self.multiple_topic_path(collection)
97
+ headers = self.get_headers(collection)
96
98
  headers[:content_type] = :json
97
- form = {topicIds: self.get_ids(topics)}
99
+ form = { :topicIds => self.get_ids(topics) }
98
100
 
99
- response = RestClient.post(url, form.to_json, headers)
100
- data = JSON.parse(response)['data']
101
+ response = RestClient.post(url, form.to_json, headers){|response, request, result| response }
102
+ data = self.analyze_response(response)
101
103
 
102
104
  data.has_key?('added') ? data['added'] : 0
103
105
  end
104
106
 
105
- def self.replace_collection_topics(site, collection_id, topics)
106
- url = self.base_url(site) + self.collection_topics_path(site, collection_id)
107
- headers = self.get_headers(site)
107
+ def self.replace_collection_topics(collection, topics)
108
+ url = self.base_url(collection) + self.multiple_topic_path(collection)
109
+ headers = self.get_headers(collection)
108
110
  headers[:content_type] = :json
109
- form = {topicIds: self.get_ids(topics)}
111
+ form = { :topicIds => self.get_ids(topics) }
110
112
 
111
- response = RestClient.put(url, form.to_json, headers)
112
- data = JSON.parse(response)['data']
113
+ response = RestClient.put(url, form.to_json, headers){|response, request, result| response }
114
+ data = self.analyze_response(response)
113
115
 
114
116
  return data.has_key?('added') ? data['added'] : 0, data.has_key?('removed') ? data['removed'] : 0
115
117
  end
116
118
 
117
- def self.remove_collection_topics(site, collection_id, topics)
118
- url = self.base_url(site) + self.collection_topics_path(site, collection_id)
119
- headers = self.get_headers(site)
119
+ def self.remove_collection_topics(collection, topics)
120
+ url = self.base_url(collection) + self.multiple_topic_path(collection)
121
+ headers = self.get_headers(collection)
120
122
  headers[:content_type] = :json
121
- form = {delete: self.get_ids(topics)}
123
+ form = { :delete => self.get_ids(topics) }
122
124
 
123
- response = RestClient.patch(url, form.to_json, headers)
124
- data = JSON.parse(response)['data']
125
+ response = RestClient.patch(url, form.to_json, headers){|response, request, result| response }
126
+ data = self.analyze_response(response)
125
127
 
126
128
  data.has_key?('removed') ? data['removed'] : 0
127
129
  end
128
130
 
129
131
  # Subscription API
130
132
  def self.get_subscriptions(network, user_id)
131
- url = self.base_url(network) + self.user_subscription_path(network.get_user_urn(user_id))
133
+ url = self.base_url(network) + self.user_subscription_path(network.get_urn_for_user(user_id))
132
134
 
133
- response = RestClient.get(url, self.get_headers(network))
134
- data = JSON.parse(response)['data']
135
+ response = RestClient.get(url, self.get_headers(network)){|response, request, result| response }
136
+ data = self.analyze_response(response)
135
137
 
136
138
  subscriptions = []
137
139
  if data.has_key?('subscriptions')
@@ -144,43 +146,46 @@ module Livefyre
144
146
  end
145
147
 
146
148
  def self.add_subscriptions(network, user_token, topics)
147
- user_id = JWT.decode(user_token, network.key)['user_id']
148
- user_urn = network.get_user_urn(user_id)
149
+ user_id = JWT.decode(user_token, network.data.key)['user_id']
150
+ user_urn = network.get_urn_for_user(user_id)
151
+
149
152
  url = self.base_url(network) + self.user_subscription_path(user_urn)
150
153
  headers = self.get_headers(network, user_token)
151
154
  headers[:content_type] = :json
152
- form = {subscriptions: self.to_subscriptions(topics, user_urn)}
155
+ form = { :subscriptions => self.to_subscriptions(topics, user_urn) }
153
156
 
154
- response = RestClient.post(url, form.to_json, headers)
155
- data = JSON.parse(response)['data']
157
+ response = RestClient.post(url, form.to_json, headers){|response, request, result| response }
158
+ data = self.analyze_response(response)
156
159
 
157
160
  data.has_key?('added') ? data['added'] : 0
158
161
  end
159
162
 
160
163
  def self.replace_subscriptions(network, user_token, topics)
161
- user_id = JWT.decode(user_token, network.key)['user_id']
162
- user_urn = network.get_user_urn(user_id)
164
+ user_id = JWT.decode(user_token, network.data.key)['user_id']
165
+ user_urn = network.get_urn_for_user(user_id)
166
+
163
167
  url = self.base_url(network) + self.user_subscription_path(user_urn)
164
168
  headers = self.get_headers(network, user_token)
165
169
  headers[:content_type] = :json
166
- form = {subscriptions: self.to_subscriptions(topics, user_urn)}
170
+ form = { :subscriptions => self.to_subscriptions(topics, user_urn) }
167
171
 
168
- response = RestClient.put(url, form.to_json, headers)
169
- data = JSON.parse(response)['data']
172
+ response = RestClient.put(url, form.to_json, headers){|response, request, result| response }
173
+ data = self.analyze_response(response)
170
174
 
171
175
  return data.has_key?('added') ? data['added'] : 0, data.has_key?('removed') ? data['removed'] : 0
172
176
  end
173
177
 
174
178
  def self.remove_subscriptions(network, user_token, topics)
175
- user_id = JWT.decode(user_token, network.key)['user_id']
176
- user_urn = network.get_user_urn(user_id)
179
+ user_id = JWT.decode(user_token, network.data.key)['user_id']
180
+ user_urn = network.get_urn_for_user(user_id)
181
+
177
182
  url = self.base_url(network) + self.user_subscription_path(user_urn)
178
183
  headers = self.get_headers(network, user_token)
179
184
  headers[:content_type] = :json
180
- form = {delete: self.to_subscriptions(topics, user_urn)}
185
+ form = { :delete => self.to_subscriptions(topics, user_urn) }
181
186
 
182
- response = RestClient.patch(url, form.to_json, headers)
183
- data = JSON.parse(response)['data']
187
+ response = RestClient.patch(url, form.to_json, headers){|response, request, result| response }
188
+ data = self.analyze_response(response)
184
189
 
185
190
  data.has_key?('removed') ? data['removed'] : 0
186
191
  end
@@ -189,8 +194,8 @@ module Livefyre
189
194
  url = self.base_url(network) + self.topic_subscription_path(topic)
190
195
  url += "?limit=#{limit}&offset=#{offset}"
191
196
 
192
- response = RestClient.get(url, self.get_headers(network))
193
- data = JSON.parse(response)['data']
197
+ response = RestClient.get(url, self.get_headers(network)){|response, request, result| response }
198
+ data = self.analyze_response(response)
194
199
 
195
200
  subscriptions = []
196
201
  if data.has_key?('subscriptions')
@@ -203,18 +208,18 @@ module Livefyre
203
208
  end
204
209
 
205
210
  # Stream API
206
- def self.get_timeline_stream(core, resource, limit=50, t_until=nil, t_since=nil)
207
- url = self.stream_base_url(core) + TIMELINE_PATH
208
- url += "?resource=#{resource}&limit=#{limit}"
209
-
210
- if t_until != nil
211
- url += "&until=#{t_until}"
212
- elsif t_since != nil
213
- url += "&since=#{t_since}"
211
+ def self.get_timeline_stream(cursor, is_next)
212
+ url = self.stream_base_url(cursor.core) + TIMELINE_PATH
213
+ url += "?resource=#{cursor.data.resource}&limit=#{cursor.data.limit}"
214
+
215
+ if is_next
216
+ url += "&since=#{cursor.data.cursor_time}"
217
+ else
218
+ url += "&until=#{cursor.data.cursor_time}"
214
219
  end
215
220
 
216
- response = RestClient.get(url, self.get_headers(core))
217
-
221
+ response = RestClient.get(url, self.get_headers(cursor.core)){|response, request, result| response }
222
+ raise ApiException.new(self, response.code) if response.code >= 400
218
223
  JSON.parse(response)
219
224
  end
220
225
 
@@ -233,11 +238,7 @@ module Livefyre
233
238
  end
234
239
 
235
240
  def self.multiple_topic_path(core)
236
- "/#{core.get_urn}:topics/"
237
- end
238
-
239
- def self.collection_topics_path(site, collection_id)
240
- "/#{site.get_urn}:collection=#{collection_id}:topics/"
241
+ "/#{core.urn}:topics/"
241
242
  end
242
243
 
243
244
  def self.user_subscription_path(user_urn)
@@ -251,7 +252,8 @@ module Livefyre
251
252
  TIMELINE_PATH = '/timeline/'
252
253
 
253
254
  def self.get_headers(core, user_token=nil)
254
- {:accepts => :json, :authorization => 'lftoken ' + (user_token == nil ? core.build_livefyre_token : user_token)}
255
+ network = LivefyreUtil::get_network_from_core(core)
256
+ {:accepts => :json, :authorization => 'lftoken ' + (user_token == nil ? network.build_livefyre_token : user_token)}
255
257
  end
256
258
 
257
259
  def self.get_ids(topics)
@@ -266,9 +268,14 @@ module Livefyre
266
268
  def self.to_subscriptions(topics, user)
267
269
  subscriptions = []
268
270
  topics.each do |topic|
269
- subscriptions << Subscription.new(topic.id, user, SubscriptionType::PERSONAL_STREAM).to_dict
271
+ subscriptions << Subscription.new(topic.id, user, SubscriptionType::PERSONAL_STREAM).to_hash
270
272
  end
271
273
  subscriptions
272
274
  end
275
+
276
+ def self.analyze_response(response)
277
+ raise ApiException.new(self, response.code) if response.code >= 400
278
+ JSON.parse(response)['data']
279
+ end
273
280
  end
274
281
  end