rightnow-client 0.0.6

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.
@@ -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
+ }