livefyre 1.3.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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