jive_api 0.0.2.pre
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.
- data/lib/jive_api.rb +449 -0
- metadata +79 -0
data/lib/jive_api.rb
ADDED
@@ -0,0 +1,449 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'httparty'
|
3
|
+
require 'net/http'
|
4
|
+
require 'uri'
|
5
|
+
require 'date'
|
6
|
+
require 'hashery/lru_hash'
|
7
|
+
|
8
|
+
module Jive
|
9
|
+
module GettableBinaryURL
|
10
|
+
def get_binary
|
11
|
+
binary_uri = URI @binary_url
|
12
|
+
http = Net::HTTP.new(binary_uri.host, binary_uri.port)
|
13
|
+
req = Net::HTTP::Get.new binary_uri.request_uri
|
14
|
+
req.basic_auth @api_instance.auth[:username], @api_instance.auth[:password]
|
15
|
+
response = http.request req
|
16
|
+
response.body
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Container
|
21
|
+
attr_reader :name, :type, :id, :raw_data, :self_uri, :subject, :display_name, :html_uri
|
22
|
+
|
23
|
+
def initialize instance, data
|
24
|
+
@raw_data = data
|
25
|
+
@api_instance = instance
|
26
|
+
@name = data["name"]
|
27
|
+
@type = data["type"]
|
28
|
+
@id = data["id"] if data.has_key? 'id'
|
29
|
+
@display_name = data["displayName"] if data.has_key? 'displayName'
|
30
|
+
@self_uri = data["resources"]["self"]["ref"] if data.has_key? 'resources'
|
31
|
+
@parent_uri = data["parent"] if data.has_key? 'parent_uri'
|
32
|
+
@subject = data["subject"] if data.has_key? 'subject'
|
33
|
+
@html_uri = data["resources"]["html"]["ref"] if (data.has_key?('resources') && data["resources"].has_key?('html'))
|
34
|
+
end
|
35
|
+
|
36
|
+
def display_path
|
37
|
+
if parent.nil?
|
38
|
+
"#{self.class}:#{@display_name}"
|
39
|
+
else
|
40
|
+
"#{parent.display_path}/#{self.class}:#{@display_name}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def uri
|
45
|
+
@self_uri
|
46
|
+
end
|
47
|
+
|
48
|
+
def parent
|
49
|
+
@api_instance.get_container_by_uri @parent_uri if @parent_uri
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class Attachment < Container
|
54
|
+
include GettableBinaryURL
|
55
|
+
attr_reader :size, :mime_type
|
56
|
+
|
57
|
+
def initialize instance, data
|
58
|
+
super instance, data
|
59
|
+
@mime_type = data['contentType']
|
60
|
+
@size = data['size']
|
61
|
+
@binary_url = data['url']
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class Content < Container
|
66
|
+
attr_reader :updated_at, :visibility, :content_id
|
67
|
+
|
68
|
+
def initialize instance, data
|
69
|
+
super instance, data
|
70
|
+
@display_name = data["name"]
|
71
|
+
@updated_at = DateTime.iso8601 data["updated"]
|
72
|
+
@visibility = data['visibility']
|
73
|
+
@content = data['content']['text']
|
74
|
+
@ref = data["resources"]["self"]["ref"]
|
75
|
+
@content_id = @ref.match(/\/api\/core\/v3\/contents\/([0-9]+)$/)[1]
|
76
|
+
end
|
77
|
+
|
78
|
+
def author
|
79
|
+
# Let's try being clever here and including the data Jive already sent back
|
80
|
+
Jive.const_get("#{@raw_data['author']['type'].capitalize}").new @api_instance, @raw_data['author']
|
81
|
+
end
|
82
|
+
|
83
|
+
def comments
|
84
|
+
@api_instance.get_container_by_uri @comments_uri if @comments_uri
|
85
|
+
end
|
86
|
+
|
87
|
+
def get
|
88
|
+
@content
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
class Document < Content
|
94
|
+
def initialize instance, data
|
95
|
+
super instance, data
|
96
|
+
@attachments_count = data['attachments'].length
|
97
|
+
@content = data['content']['text']
|
98
|
+
@content_type = data['content']['type']
|
99
|
+
@display_name = data["subject"]
|
100
|
+
@attachments_uri = data["resources"]["attachments"]["ref"] if data["resources"].has_key? "attachments"
|
101
|
+
end
|
102
|
+
|
103
|
+
def get
|
104
|
+
@content
|
105
|
+
end
|
106
|
+
|
107
|
+
def attachments
|
108
|
+
@api_instance.get_container_by_uri @attachments_uri if @attachments_uri
|
109
|
+
end
|
110
|
+
|
111
|
+
def has_attachments?
|
112
|
+
@attachments_count > 0
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
class Discussion < Content
|
118
|
+
def initialize instance, data
|
119
|
+
super instance, data
|
120
|
+
@display_name = data['subject']
|
121
|
+
@messages_uri = data['resources']['messages']['ref']
|
122
|
+
end
|
123
|
+
|
124
|
+
def messages
|
125
|
+
@api_instance.get_container_by_uri @messages_uri if @messages_uri
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
class File < Content
|
130
|
+
include GettableBinaryURL
|
131
|
+
attr_reader :mime_type
|
132
|
+
|
133
|
+
def initialize instance, data
|
134
|
+
super instance, data
|
135
|
+
@binary_url = data['binaryURL']
|
136
|
+
@mime_type = data['contentType']
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
class Poll < Content
|
143
|
+
def initialize instance, data
|
144
|
+
super instance, data
|
145
|
+
@display_name = data['subject']
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
class Comment < Content
|
150
|
+
end
|
151
|
+
|
152
|
+
class Post < Content
|
153
|
+
def initialize instance, data
|
154
|
+
super instance, data
|
155
|
+
@display_name = data["subject"]
|
156
|
+
@comments_uri = data["resources"]["comments"]["ref"] if data["resources"].has_key? "comments"
|
157
|
+
@attachments_uri = data["resources"]["attachments"]["ref"] if data["resources"].has_key? "attachments"
|
158
|
+
end
|
159
|
+
|
160
|
+
def attachments
|
161
|
+
@api_instance.get_container_by_uri @attachments_uri if @attachments_uri
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
class Message < Content
|
166
|
+
def initialize instance, data
|
167
|
+
super instance, data
|
168
|
+
@content = data["content"]["text"]
|
169
|
+
end
|
170
|
+
|
171
|
+
def get
|
172
|
+
@content
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
class Update < Content
|
177
|
+
def initialize instance, data
|
178
|
+
super instance, data
|
179
|
+
@display_name = data['subject']
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
class Favorite < Content
|
184
|
+
end
|
185
|
+
|
186
|
+
class Task < Content
|
187
|
+
end
|
188
|
+
|
189
|
+
class Idea < Content
|
190
|
+
end
|
191
|
+
|
192
|
+
class Person < Container
|
193
|
+
attr_reader :display_name, :userid, :status
|
194
|
+
|
195
|
+
def initialize instance, data
|
196
|
+
super instance, data
|
197
|
+
@userid = data["jive"]["username"]
|
198
|
+
@status = data["status"]
|
199
|
+
@blog_uri = data["resources"]["blog"]["ref"] if data["resources"].has_key? 'blog'
|
200
|
+
end
|
201
|
+
|
202
|
+
def blog
|
203
|
+
@blog_uri ? @api_instance.get_container_by_uri(@blog_uri) : nil
|
204
|
+
end
|
205
|
+
|
206
|
+
def content filters = []
|
207
|
+
filters += ["author(#{uri})"]
|
208
|
+
@api_instance.contents :query => { :filter => filters }
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
class Place < Container
|
213
|
+
attr_reader :description, :status, :ref, :place_id
|
214
|
+
|
215
|
+
def initialize instance, data
|
216
|
+
super instance, data
|
217
|
+
@description = data["description"]
|
218
|
+
@status = data["status"]
|
219
|
+
@ref = data["resources"]["self"]["ref"]
|
220
|
+
@place_id = @ref.match(/\/api\/core\/v3\/places\/([0-9]+)$/)[1]
|
221
|
+
end
|
222
|
+
|
223
|
+
def content
|
224
|
+
filter = "place(#{@self_uri})"
|
225
|
+
@api_instance.paginated_get('/api/core/v3/contents', :query => { :filter => "#{filter}" }).map do |item|
|
226
|
+
object_class = Jive.const_get "#{item['type'].capitalize}"
|
227
|
+
object_class.new @api_instance, item
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def places(filter = [], options = {})
|
232
|
+
options.merge!({ :filter => filter })
|
233
|
+
@api_instance.paginated_get("#{uri}/places", :query => options).map do |item|
|
234
|
+
object_class = Jive.const_get "#{item['type'].capitalize}"
|
235
|
+
object_class.new @api_instance, item
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
end
|
240
|
+
|
241
|
+
class Group < Place
|
242
|
+
def initialize instance, data
|
243
|
+
super instance, data
|
244
|
+
end
|
245
|
+
|
246
|
+
def creator
|
247
|
+
Jive.const_get("#{@raw_data['creator']['type'].capitalize}").new @api_instance, @raw_data['creator']
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
class Space < Place
|
252
|
+
def initialize instance, data
|
253
|
+
super instance, data
|
254
|
+
end
|
255
|
+
|
256
|
+
def sub_spaces
|
257
|
+
places ["type(space)"]
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
class Project < Place
|
262
|
+
def initialize instance, data
|
263
|
+
super instance, data
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
class Blog < Place
|
268
|
+
def initialize instance, data
|
269
|
+
super instance, data
|
270
|
+
@display_name = data["name"]
|
271
|
+
@contents_uri = data["resources"]["contents"]["ref"]
|
272
|
+
end
|
273
|
+
|
274
|
+
def posts
|
275
|
+
@api_instance.paginated_get(@contents_uri).map { |post| Post.new @api_instance, post }
|
276
|
+
end
|
277
|
+
|
278
|
+
end
|
279
|
+
|
280
|
+
class Api
|
281
|
+
attr_reader :object_cache, :auth
|
282
|
+
include HTTParty
|
283
|
+
|
284
|
+
disable_rails_query_string_format
|
285
|
+
|
286
|
+
def inspect
|
287
|
+
# Don't show the attribute cache. It gets enormous.
|
288
|
+
attributes_no_object_cache = self.instance_variables.reject { |var| var.to_s == '@object_cache' }
|
289
|
+
attributes_as_nice_string = attributes_no_object_cache.map { |attr| "#{attr}: #{self.instance_variable_get(attr).inspect}" }.join ", "
|
290
|
+
"#<#{self.class}:#{'%x' % (self.object_id << 1)} #{attributes_as_nice_string}>"
|
291
|
+
end
|
292
|
+
|
293
|
+
class JSONResponseParser < HTTParty::Parser
|
294
|
+
SupportFormats = { "application/json" => :json }
|
295
|
+
def parse
|
296
|
+
body.slice!(/throw.*;\s*/)
|
297
|
+
super
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
def initialize username, password, uri
|
302
|
+
@object_cache = Hashery::LRUHash.new 10000
|
303
|
+
@auth = { :username => username, :password => password }
|
304
|
+
self.class.base_uri uri
|
305
|
+
end
|
306
|
+
|
307
|
+
def api_version
|
308
|
+
self.class.get '/api/version', {:basic_auth => @auth}
|
309
|
+
end
|
310
|
+
|
311
|
+
def paginated_get path, options = {}, &block
|
312
|
+
result = []
|
313
|
+
next_uri = path
|
314
|
+
|
315
|
+
options.merge!({:basic_auth => @auth})
|
316
|
+
limit = 0
|
317
|
+
# count doesn't work as expected in paginated requests, so we have a limit option
|
318
|
+
if options.has_key? :limit
|
319
|
+
limit = options[:limit].to_i
|
320
|
+
options.delete :limit
|
321
|
+
end
|
322
|
+
|
323
|
+
results_so_far = 0
|
324
|
+
begin
|
325
|
+
response = self.class.get next_uri, options
|
326
|
+
raise Error if response.parsed_response.has_key? 'error'
|
327
|
+
options.delete :query
|
328
|
+
next_uri = (response.parsed_response["links"] and response.parsed_response["links"]["next"] ) ? response.parsed_response["links"]["next"] : nil
|
329
|
+
list = response.parsed_response["list"]
|
330
|
+
list = list ? list : []
|
331
|
+
result.concat list
|
332
|
+
if block_given?
|
333
|
+
list.map do |item|
|
334
|
+
yield ((Jive.const_get "#{item['type'].capitalize}").new self, item)
|
335
|
+
end
|
336
|
+
end
|
337
|
+
results_so_far+=list.count
|
338
|
+
end while next_uri && ((limit == 0) || (results_so_far < limit))
|
339
|
+
result
|
340
|
+
end
|
341
|
+
|
342
|
+
def people options = {}, &block
|
343
|
+
get_containers_by_type 'people', options, &block
|
344
|
+
end
|
345
|
+
|
346
|
+
def person_by_username username
|
347
|
+
get_container_by_uri "/api/core/v3/people/username/#{username}"
|
348
|
+
end
|
349
|
+
|
350
|
+
def place_by_id place_id
|
351
|
+
get_container_by_uri "/api/core/v3/places/#{place_id}"
|
352
|
+
end
|
353
|
+
|
354
|
+
def content_by_id content_id
|
355
|
+
get_container_by_uri "/api/core/v3/contents/#{content_id}"
|
356
|
+
end
|
357
|
+
|
358
|
+
def places options = {}, &block
|
359
|
+
get_containers_by_type 'places', options, &block
|
360
|
+
end
|
361
|
+
|
362
|
+
def contents options = {}, &block
|
363
|
+
get_containers_by_type 'contents', options, &block
|
364
|
+
end
|
365
|
+
|
366
|
+
def activities options = {}, &block
|
367
|
+
get_containers_by_type 'activity', options, &block
|
368
|
+
end
|
369
|
+
|
370
|
+
def get_containers_by_type type, options, &block
|
371
|
+
next_uri = "/api/core/v3/#{type}"
|
372
|
+
if block_given?
|
373
|
+
paginated_get(next_uri,options, &block)
|
374
|
+
else
|
375
|
+
paginated_get(next_uri, options).map do |data|
|
376
|
+
object_class = Jive.const_get "#{data['type'].capitalize}"
|
377
|
+
o = object_class.new self, data
|
378
|
+
@object_cache[o.uri] = o
|
379
|
+
end
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
def get_container_by_uri uri
|
384
|
+
# Deliver from the object cache if we have it
|
385
|
+
return @object_cache[uri] if @object_cache.has_key? uri
|
386
|
+
data = self.class.get uri, { :basic_auth => @auth }
|
387
|
+
# raise Error if data.parsed_response.has_key? 'error'
|
388
|
+
return nil if data.parsed_response.has_key? 'error'
|
389
|
+
# We handle both lists and single items with this
|
390
|
+
if data.parsed_response.has_key? "list"
|
391
|
+
data.parsed_response['list'].map do |item|
|
392
|
+
object_class = Jive.const_get "#{item['type'].capitalize}"
|
393
|
+
o = object_class.new self, item
|
394
|
+
@object_cache[o.uri] = o
|
395
|
+
o
|
396
|
+
end
|
397
|
+
else
|
398
|
+
object_class = Jive.const_get "#{data.parsed_response['type'].capitalize}"
|
399
|
+
o = object_class.new self, data
|
400
|
+
@object_cache[o.uri] = o
|
401
|
+
o
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
def places_by_filter filter, options = {}
|
406
|
+
options.merge!({ :query => { :filter => filter }})
|
407
|
+
places options
|
408
|
+
end
|
409
|
+
|
410
|
+
def places_by_type object_type, options = {}
|
411
|
+
places_by_filter "type(#{object_type})", options
|
412
|
+
end
|
413
|
+
|
414
|
+
def blogs(options = {})
|
415
|
+
places_by_type "blog", options
|
416
|
+
end
|
417
|
+
|
418
|
+
def spaces(options = {})
|
419
|
+
places_by_type "space", options
|
420
|
+
end
|
421
|
+
|
422
|
+
def groups(options = {})
|
423
|
+
places_by_type "group", options
|
424
|
+
end
|
425
|
+
|
426
|
+
def contents_by_username username
|
427
|
+
user = person_by_username username
|
428
|
+
contents :query => { :filter => "author(#{user.self_uri})" }
|
429
|
+
end
|
430
|
+
|
431
|
+
def search type, query, filters = []
|
432
|
+
filters += ["search(#{query})"]
|
433
|
+
paginated_get("/api/core/v3/search/#{type}", { :query => { :filter => filters } } ).map do |data|
|
434
|
+
object_class = Jive.const_get "#{data['type'].capitalize}"
|
435
|
+
object_class.new self, data
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
def main_space
|
440
|
+
places_by_filter("entityDescriptor(14,1)")[0]
|
441
|
+
end
|
442
|
+
|
443
|
+
headers 'Accept' => 'application/json'
|
444
|
+
headers 'Content-Type' => 'application/json'
|
445
|
+
format :json
|
446
|
+
parser JSONResponseParser
|
447
|
+
|
448
|
+
end
|
449
|
+
end
|
metadata
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jive_api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2.pre
|
5
|
+
prerelease: 6
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Andrew Beresford
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-02-11 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: httparty
|
16
|
+
requirement: &70148430451680 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.10.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70148430451680
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: hashery
|
27
|
+
requirement: &70148430451060 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.1.0
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70148430451060
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rake
|
38
|
+
requirement: &70148430450660 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70148430450660
|
47
|
+
description: Jive API Connector for Ruby
|
48
|
+
email: beezly@beezly.org.uk
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- lib/jive_api.rb
|
54
|
+
homepage: http://github.com/beezly/jive-ruby
|
55
|
+
licenses: []
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options: []
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ! '>'
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: 1.3.1
|
72
|
+
requirements: []
|
73
|
+
rubyforge_project:
|
74
|
+
rubygems_version: 1.8.5
|
75
|
+
signing_key:
|
76
|
+
specification_version: 3
|
77
|
+
summary: Jive API
|
78
|
+
test_files: []
|
79
|
+
has_rdoc:
|