rightnow-client 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,19 @@
1
+ require 'virtus'
2
+
3
+ module Rightnow
4
+ module Models
5
+ class Field
6
+ include Virtus
7
+
8
+ attribute :id, Integer
9
+ attribute :value, String
10
+ attribute :name, String
11
+ attribute :type, Integer
12
+
13
+ def post_type_field= type
14
+ self.name = type['name']
15
+ self.type = type['type']
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,58 @@
1
+ require 'virtus'
2
+ require 'rightnow/models/user'
3
+ require 'rightnow/models/field'
4
+
5
+ module Rightnow
6
+ module Models
7
+ class Post
8
+ include Virtus
9
+
10
+ # UserGet attributes
11
+ attribute :uri, String
12
+ attribute :post_type, Hash[String => String]
13
+ attribute :created, Integer
14
+ attribute :created_by, User
15
+ attribute :last_edited, Integer
16
+ attribute :last_edited_by, User
17
+ attribute :event_start, Time
18
+ attribute :event_end, Time
19
+ attribute :event_time_zone, String
20
+ attribute :title, String
21
+ attribute :status, Integer
22
+ attribute :comment_count, Integer
23
+ attribute :view_count, Integer
24
+ attribute :rating_count, Integer
25
+ attribute :rating_total, Integer
26
+ attribute :flag_count, Integer
27
+ attribute :fields, Array[Field]
28
+
29
+ # Search only attributes
30
+ attribute :id, Integer
31
+ attribute :hash, String
32
+ attribute :web_url, String
33
+ attribute :hive_id, Integer
34
+ attribute :answer_id, Integer
35
+ attribute :answer_selected_by_id, Integer
36
+ attribute :answer_selected, Boolean # ?
37
+ attribute :last_activity, Integer
38
+ attribute :preview, String
39
+
40
+ def post_type_id= value
41
+ self.post_type['id'] = value
42
+ end
43
+
44
+ def created_at
45
+ Time.at(created)
46
+ end
47
+
48
+ def last_edited_at
49
+ Time.at(last_edited)
50
+ end
51
+
52
+ def last_activity_at
53
+ Time.at(last_activity)
54
+ end
55
+
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,13 @@
1
+ require 'virtus'
2
+
3
+ module Rightnow
4
+ module Models
5
+ class Reputation
6
+ include Virtus
7
+
8
+ attribute :level, String
9
+ attribute :score, Integer
10
+ attribute :avatar, String
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,44 @@
1
+ require 'virtus'
2
+ require 'rightnow/models/reputation'
3
+
4
+ module Rightnow
5
+ module Models
6
+ class User
7
+ include Virtus
8
+
9
+ attribute :guid, String
10
+ attribute :hash, String, default: lambda { |u,v| u.api_uri.scan(/[0-9a-z]{10}\z/).first }
11
+ attribute :web_uri, String
12
+ attribute :api_uri, String
13
+ attribute :login_id, String
14
+ attribute :user_id, Integer
15
+ attribute :name, String
16
+ attribute :avatar, String
17
+ attribute :email, String
18
+ attribute :type, Integer
19
+ attribute :status, Integer
20
+ attribute :guid, Integer
21
+ attribute :created, Integer
22
+ attribute :last_login, Integer
23
+ attribute :buddy_count, Integer
24
+ attribute :group_count, Integer
25
+ attribute :hive_count, Integer
26
+ attribute :post_count, Integer
27
+ attribute :comment_count, Integer
28
+ attribute :comments_selected_as_best_answer_count, Integer
29
+ attribute :reputation, Reputation
30
+
31
+ def created_at
32
+ Time.at(created)
33
+ end
34
+
35
+ def last_login_at
36
+ Time.at(last_login)
37
+ end
38
+
39
+ def uri= value
40
+ self.api_uri = value
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,3 @@
1
+ module Rightnow
2
+ VERSION = "0.0.6"
3
+ end
data/rightnow.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rightnow/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "rightnow-client"
8
+ gem.version = Rightnow::VERSION
9
+ gem.authors = ["Adrien Jarthon"]
10
+ gem.email = ["adrien.jarthon@dimelo.com"]
11
+ gem.description = %q{Rightnow API Ruby wrapper}
12
+ gem.summary = %q{Ruby wrapper for the Oracle Rightnow Social API v2}
13
+ gem.homepage = "https://github.com/dimelo/rightnow"
14
+
15
+ gem.add_dependency 'faraday', '>= 0.8.0'
16
+ gem.add_dependency 'virtus', '>= 0.5.3'
17
+ gem.add_dependency 'typhoeus', '>= 0.5.0'
18
+ gem.add_development_dependency 'rspec', '~> 2.6'
19
+ gem.add_development_dependency 'webmock', '~> 1.8'
20
+ gem.add_development_dependency 'rake'
21
+ gem.files = `git ls-files`.split($/)
22
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
23
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
24
+ gem.require_paths = ["lib"]
25
+ end
@@ -0,0 +1,197 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rightnow::Client do
4
+ let(:client) { Rightnow::Client.new "http://something", :api_key => "API", :secret_key => "SECRET" }
5
+
6
+ describe ".initialize" do
7
+ it "should store host and default attributes" do
8
+ client = Rightnow::Client.new "http://community.company.com"
9
+ client.host.should == "http://community.company.com"
10
+ client.api_key.should == nil
11
+ client.secret_key.should == nil
12
+ client.version.should == '2010-05-15'
13
+ end
14
+
15
+ it "accepts options" do
16
+ client = Rightnow::Client.new "host", :api_key => "APIKEY", :secret_key => "SECRETKEY", :version => '2042-13-13'
17
+ client.api_key.should == "APIKEY"
18
+ client.secret_key.should == "SECRETKEY"
19
+ client.version.should == '2042-13-13'
20
+ end
21
+ end
22
+
23
+ describe '#search' do
24
+ it "compute correct request" do
25
+ stub_request(:get, "http://something/api/endpoint?Action=Search&ApiKey=API&PermissionedAs=hl.api@hivelive.com&Signature=nwmG/dgt9MLvq1CXWTtSLqcaaaY=&SignatureVersion=2&format=json&limit=20&objects=Posts&sort=az&start=21&term=white&version=2010-05-15").to_return :body => '[]'
26
+ client.search(:term => 'white', :sort => 'az', :page => 2).should == []
27
+ end
28
+
29
+ it "returns correctly parsed response" do
30
+ stub_request(:get, /.*/).to_return :body => fixture('search.json')
31
+ response = client.search
32
+ response.should have(5).items
33
+ response.first.should be_instance_of(Rightnow::Models::Post)
34
+ end
35
+ end
36
+
37
+ describe '#post_get' do
38
+ it "compute correct request" do
39
+ stub_request(:get, "http://something/api/endpoint?Action=PostGet&ApiKey=API&PermissionedAs=hl.api@hivelive.com&Signature=bFdCqLpLcCHT3jQEz7nndKrVVk8=&SignatureVersion=2&format=json&postHash=fa8e6cc713&version=2010-05-15").to_return :body => '{}'
40
+ client.post_get("fa8e6cc713").should be_nil
41
+ end
42
+
43
+ context "with stubbed answer" do
44
+ before { stub_request(:get, /.*/).to_return :body => fixture('post_get.json') }
45
+
46
+ it "returns correctly parsed response" do
47
+ response = client.post_get "fa8e6cc713"
48
+ response.should be_instance_of(Rightnow::Models::Post)
49
+ response.view_count.should == 795
50
+ response.hash.should == "fa8e6cc713"
51
+ end
52
+
53
+ it "accepts multiple elements" do
54
+ posts = client.post_get ["fa8e6cc713", "fa8e6cb714"]
55
+ posts.should have(2).items
56
+ posts.first.should be_instance_of(Rightnow::Models::Post)
57
+ end
58
+
59
+ it "accepts Rightnow::Post instances" do
60
+ post = Rightnow::Models::Post.new(:hash => "fa8e6cc713")
61
+ res = client.post_get post
62
+ res.should be_instance_of(Rightnow::Models::Post)
63
+ res.view_count.should == 795
64
+ end
65
+
66
+ it "merges input Rightnow::Post instance with results" do
67
+ post = Rightnow::Models::Post.new(:hash => "fa8e6cc713")
68
+ res = client.post_get post
69
+ res.view_count.should == 795
70
+ res.hash.should == "fa8e6cc713"
71
+ end
72
+ end
73
+ end
74
+
75
+ describe '#comment_list' do
76
+ it "compute correct request" do
77
+ stub_request(:get, "http://something/api/endpoint?Action=CommentList&ApiKey=API&PermissionedAs=toto&Signature=0J8ggfqObzTGxydijxgdLSvNzds=&SignatureVersion=2&format=json&postHash=fa8e6cc713&version=2010-05-15").to_return :body => '{"comments": []}'
78
+ client.comment_list("fa8e6cc713", as: 'toto').should == []
79
+ # the `as: 'toto'` hack is just here to change the signature,
80
+ # webmock doesn't like the original one: AEyyp+MpfxT/DlhRqAfzvT1dFCM
81
+ end
82
+
83
+ it "raise error in case of bad return value" do
84
+ stub_request(:get, /.*/).to_return body: '{}'
85
+ expect {
86
+ client.comment_list "fa8e6cc713"
87
+ }.to raise_error(Rightnow::Error, "Missing `comments` key in CommentList response: {}")
88
+ end
89
+
90
+ context "with stubbed answer" do
91
+ before { stub_request(:get, /.*/).to_return body: fixture('comment_list.json') }
92
+
93
+ it "returns correctly parsed response" do
94
+ response = client.comment_list "fa8e6cc713"
95
+ response.should have(3).items
96
+ response.first.should be_instance_of(Rightnow::Models::Comment)
97
+ end
98
+ end
99
+ end
100
+
101
+ describe '#comment_add' do
102
+ it "compute correct request" do
103
+ pending "couldn't get this test passing" do
104
+ stub_request(:post, "http://something/api/endpoint").with(:body => {"Action"=>"CommentAdd", "ApiKey"=>"API", "PermissionedAs"=>"toto", "Signature"=>"kJXXoPZ7xexKxv8duTYmtS519GY=", "SignatureVersion"=>"2", "format"=>"json", "payload"=>"<?xml version='1.0'?><comments><comment><value><![CDATA[test]]></value></comment></comments>", "postHash"=>"fa8e6cc713", "version"=>"2010-05-15"}).to_return :body => ""
105
+ client.comment_add("fa8e6cc713", 'test', as: 'toto')
106
+ end
107
+ end
108
+
109
+ it "return comment model" do
110
+ stub_request(:post, "http://something/api/endpoint").to_return :body => fixture('comment_add.json')
111
+ client.comment_add("fa8e6cc713", 'test', as: 'toto').should be_instance_of Rightnow::Models::Comment
112
+ end
113
+ end
114
+
115
+ describe '#comment_update' do
116
+
117
+ it "return comment model" do
118
+ stub_request(:post, "http://something/api/endpoint").to_return :body => fixture('comment_add.json')
119
+ client.comment_update(777, 'test', as: 'toto').should be_instance_of Rightnow::Models::Comment
120
+ end
121
+ end
122
+
123
+ describe '#comment_delete' do
124
+ it "compute correct request" do
125
+ stub_request(:get, "http://something/api/endpoint?Action=CommentDelete&ApiKey=API&PermissionedAs=hl.api@hivelive.com&Signature=BdDIajOi/eZprayZ8X8eEsH1yb4=&SignatureVersion=2&commentId=777&format=json&version=2010-05-15").to_return body: '{"comment": {"id": 777}}'
126
+ client.comment_delete(777).should == {'comment' => {'id' => 777}}
127
+ end
128
+ end
129
+
130
+ describe "#request" do
131
+ it "compute correct request" do
132
+ stub_request(:get, "http://something/api/endpoint?Action=UserList&ApiKey=API&PermissionedAs=hl.api@hivelive.com&Signature=wLTpdU5EEyYBlDg%2BMz5AGEAPs98=&SignatureVersion=2&format=json&version=2010-05-15").to_return :body => '{}'
133
+ client.request('UserList').should == {}
134
+ end
135
+
136
+ it "raise correct exceptions on 401" do
137
+ stub_request(:get, /.*/).to_return(:status => 401, :body => '{"error":{"message":"invalid parameter","code":42}}')
138
+ expect {
139
+ client.request 'UserList'
140
+ }.to raise_error(Rightnow::Error, "invalid parameter (42)")
141
+ end
142
+
143
+ it "raise correct exceptions on error without details" do
144
+ stub_request(:get, /.*/).to_return(:status => 401, :body => '{"something":"happened"}')
145
+ expect {
146
+ client.request 'UserList'
147
+ }.to raise_error(Rightnow::Error, 'API returned 401 without explanation: {"something":"happened"}')
148
+ end
149
+
150
+ it "raise correct exceptions on bad JSON" do
151
+ stub_request(:get, /.*/).to_return(:status => 200, :body => 'bad')
152
+ expect {
153
+ client.request 'UserList'
154
+ }.to raise_error(Rightnow::Error, 'Bad JSON received: "bad"')
155
+ end
156
+
157
+ it "parse JSON response correctly" do
158
+ stub_request(:get, /.*/).
159
+ to_return(:status => 200, :body => fixture('search.json'))
160
+ results = client.request 'Search'
161
+ results.should have(5).items
162
+ results.first.should == fixture('post.rb', :ruby)
163
+ end
164
+ end
165
+
166
+ describe "#comment_xml_paypload" do
167
+ it "should generate correct XML payload" do
168
+ client.send(:comment_xml_payload, "test").to_s.should == "<?xml version='1.0'?><comments><comment><value><![CDATA[test]]></value></comment></comments>"
169
+ end
170
+ end
171
+
172
+ describe "#signed_params" do
173
+ subject { client.send :signed_params, "Something" }
174
+
175
+ it { should include('Action' => 'Something', 'ApiKey' => 'API') }
176
+ it { should include('version' => '2010-05-15', 'SignatureVersion' => '2') }
177
+ it { should include('PermissionedAs' => 'hl.api@hivelive.com') }
178
+ it { should include('Signature' => 'vIONtWGXvdAG/McOTM0KuFD+O2g=') }
179
+ it { should include('format' => 'json') }
180
+ its(:size) { should == 7 }
181
+
182
+ context "with custom permission" do
183
+ subject { client.send :signed_params, "Something", :as => 'email@domain.com' }
184
+
185
+ it { should include('PermissionedAs' => 'email@domain.com') }
186
+ it { should include('Signature' => 'i66NBNtwG21kxDHYOVMQpb7bhzk=') }
187
+ it { should_not include('as') }
188
+ end
189
+
190
+ context "with custom values" do
191
+ subject { client.send :signed_params, "Something", 'term' => 'white' }
192
+
193
+ it { should include('Signature' => 'vIONtWGXvdAG/McOTM0KuFD+O2g=') }
194
+ it { should include('term' => 'white') }
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,21 @@
1
+ {"comment":{
2
+ "id":96082,
3
+ "uri":"http://community.belgacom.be/api/comments/96082",
4
+ "created":1357558716, "createdBy":{
5
+ "hash":"50ed7819d1",
6
+ "uri":"http://community.belgacom.be/api/users/50ed7819d1",
7
+ "loginId":"50ed7819d1",
8
+ "name":"Adrien .",
9
+ "avatar":"http:\/\/community.belgacom.be\/common\/images\/avatars\/user\/default.jpg" },
10
+ "lastEdited":1357558716, "lastEditedBy":{
11
+ "hash":"50ed7819d1",
12
+ "uri":"http://community.belgacom.be/api/users/50ed7819d1",
13
+ "loginId":"50ed7819d1",
14
+ "name":"Adrien .",
15
+ "avatar":"http:\/\/community.belgacom.be\/common\/images\/avatars\/user\/default.jpg" },
16
+ "status":1,
17
+ "hiveHash":"e93ba3507b",
18
+ "hiveName":"Autres",
19
+ "postHash":"e41899881f",
20
+ "postName":"Site - lenteur",
21
+ "value":"Oui, et ca dure..."}}
@@ -0,0 +1,120 @@
1
+ {
2
+ "permissionsForRequestingUser":{
3
+ "admin":0,
4
+ "tagCreate":0,
5
+ "tagApplyOwn":0,
6
+ "tagApplyAll":0,
7
+ "postCreate":0,
8
+ "postViewOwn":1,
9
+ "postViewAll":1,
10
+ "postEditOwn":0,
11
+ "postEditAll":0,
12
+ "commentCreate":0,
13
+ "commentViewOwn":1,
14
+ "commentViewAll":1,
15
+ "commentEditOwn":0,
16
+ "commentEditAll":0,
17
+ "flaggingEnabled":1,
18
+ "ratingEnabled":0
19
+ },
20
+ "comments":[{
21
+ "id":94224,
22
+ "parentId":null,
23
+ "uri":"http://communityname.com/api/comments/94224",
24
+ "status":1,
25
+ "created":1355765048,
26
+ "createdBy":{
27
+ "name":"Francoise .",
28
+ "guid":"35948",
29
+ "avatar":"http://communityname.com/common/images/avatars/user/default.jpg",
30
+ "webUri":"http://communityname.com/people/3e2ce69336",
31
+ "apiUri":"http://communityname.com/api/users/3e2ce69336"
32
+ },
33
+ "lastEdited":1355765048,
34
+ "lastEditedBy":{
35
+ "name":"Francoise .",
36
+ "guid":"35948",
37
+ "avatar":"http://communityname.com/common/images/avatars/user/default.jpg",
38
+ "webUri":"http://communityname.com/people/3e2ce69336",
39
+ "apiUri":"http://communityname.com/api/users/3e2ce69336"
40
+ },
41
+ "ratingCount":0,
42
+ "ratingValueTotal":0,
43
+ "ratingWeighted":0,
44
+ "ratedByRequestingUser":{
45
+ "created":null,
46
+ "ratingValue":null
47
+ },
48
+ "flaggedCount":0,
49
+ "flaggedByRequestingUser":{
50
+ "created":null
51
+ },
52
+ "value":"<p>\r\n\tEn ce qui me concerne, ce n&#39;est pas le site qui est lent, c&#39;est l&#39;ensemble de ma connexion qui se tra&icirc;ne et impossible d&#39;avoir une r&eacute;ponse quand je demande, depuis 1 an, quand la ligne sera enfin convenable.&nbsp; La fibre optique a &eacute;t&eacute; plac&eacute;e &agrave; environ 150 m&egrave;tres de chez moi mais nul ne sait ni le jour ni l&#39;heure du raccord aux habitations.<\/p>\r\n<p>\r\n\tConclusion : ma facture est de 100 %, ma connexion maximum de 10 %.<\/p>\r\n<p>\r\n\tInsupportable !<\/p>"
53
+ },{
54
+ "id":94226,
55
+ "parentId":null,
56
+ "uri":"http://communityname.com/api/comments/94226",
57
+ "status":1,
58
+ "created":1355766489,
59
+ "createdBy":{
60
+ "name":"Max .",
61
+ "guid":"23325",
62
+ "avatar":"http://communityname.com/files/3db01561ac/cellulo&#45;armored&#45;tux.png",
63
+ "webUri":"http://communityname.com/people/a964f9cfd3",
64
+ "apiUri":"http://communityname.com/api/users/a964f9cfd3"
65
+ },
66
+ "lastEdited":1355766489,
67
+ "lastEditedBy":{
68
+ "name":"Max .",
69
+ "guid":"23325",
70
+ "avatar":"http://communityname.com/files/3db01561ac/cellulo&#45;armored&#45;tux.png",
71
+ "webUri":"http://communityname.com/people/a964f9cfd3",
72
+ "apiUri":"http://communityname.com/api/users/a964f9cfd3"
73
+ },
74
+ "ratingCount":0,
75
+ "ratingValueTotal":0,
76
+ "ratingWeighted":0,
77
+ "ratedByRequestingUser":{
78
+ "created":null,
79
+ "ratingValue":null
80
+ },
81
+ "flaggedCount":0,
82
+ "flaggedByRequestingUser":{
83
+ "created":null
84
+ },
85
+ "value":"<p>\r\n\tD&#39;accord avec vous, mais ce n&#39;est pas l&#39;objet du pr&eacute;sent message...<img alt=\"surprise\" height=\"20\" src=\"http:\/\/communityname.com\/common\/js\/ckeditor\/plugins\/smiley\/images\/omg_smile.gif\" title=\"surprise\" width=\"20\" \/><\/p>"
86
+ },{
87
+ "id":94233,
88
+ "parentId":null,
89
+ "uri":"http://communityname.com/api/comments/94233",
90
+ "status":1,
91
+ "created":1355768533,
92
+ "createdBy":{
93
+ "name":"euronamur",
94
+ "guid":"1204",
95
+ "avatar":"http://communityname.com/files/6e10df597f/Oeildouble.jpg",
96
+ "webUri":"http://communityname.com/people/427e63c8db",
97
+ "apiUri":"http://communityname.com/api/users/427e63c8db"
98
+ },
99
+ "lastEdited":1355768533,
100
+ "lastEditedBy":{
101
+ "name":"euronamur",
102
+ "guid":"1204",
103
+ "avatar":"http://communityname.com/files/6e10df597f/Oeildouble.jpg",
104
+ "webUri":"http://communityname.com/people/427e63c8db",
105
+ "apiUri":"http://communityname.com/api/users/427e63c8db"
106
+ },
107
+ "ratingCount":0,
108
+ "ratingValueTotal":0,
109
+ "ratingWeighted":0,
110
+ "ratedByRequestingUser":{
111
+ "created":null,
112
+ "ratingValue":null
113
+ },
114
+ "flaggedCount":0,
115
+ "flaggedByRequestingUser":{
116
+ "created":null
117
+ },
118
+ "value":"<p>\r\n\tM&ecirc;me probl&egrave;me pour moi Max , sur le forum.<img alt=\"wink\" height=\"20\" src=\"http:\/\/communityname.com\/common\/js\/ckeditor\/plugins\/smiley\/images\/wink_smile.gif\" title=\"wink\" width=\"20\" \/><\/p>\r\n<p>\r\n\t&nbsp;<\/p>\r\n<p>\r\n\t@+Gilbert<img alt=\"cool\" height=\"20\" src=\"http:\/\/communityname.com\/common\/js\/ckeditor\/plugins\/smiley\/images\/shades_smile.gif\" title=\"cool\" width=\"20\" \/><\/p>"
119
+ }]
120
+ }