yammer_api 0.1.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.
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/lib/yammer_api.rb +33 -0
- data/lib/yammer_api/api.rb +8 -0
- data/lib/yammer_api/api/feed.rb +195 -0
- data/lib/yammer_api/api/likes.rb +33 -0
- data/lib/yammer_api/api/messages.rb +65 -0
- data/lib/yammer_api/api/users.rb +22 -0
- data/lib/yammer_api/base.rb +41 -0
- data/lib/yammer_api/client.rb +31 -0
- data/lib/yammer_api/errors.rb +35 -0
- data/lib/yammer_api/helper.rb +10 -0
- data/lib/yammer_api/mash.rb +13 -0
- data/lib/yammer_api/post.rb +39 -0
- data/lib/yammer_api/request/request.rb +83 -0
- data/lib/yammer_api/user.rb +24 -0
- data/lib/yammer_api/version.rb +3 -0
- data/spec/cases/client_spec.rb +66 -0
- data/spec/cases/post_spec.rb +26 -0
- data/spec/cases/user_spec.rb +30 -0
- data/spec/cases/yammer_api_spec.rb +14 -0
- data/spec/fixtures/about_topic.json +103 -0
- data/spec/fixtures/following.json +388 -0
- data/spec/fixtures/from_user.json +272 -0
- data/spec/fixtures/in_group.json +92 -0
- data/spec/fixtures/network_feed.json +1 -0
- data/spec/fixtures/newly_posted.json +75 -0
- data/spec/fixtures/private.json +120 -0
- data/spec/fixtures/received.json +100 -0
- data/spec/fixtures/sent.json +80 -0
- data/spec/fixtures/single_post.json +55 -0
- data/spec/fixtures/single_user.json +16 -0
- data/spec/spec_helper.rb +15 -0
- data/yammer_api.gemspec +28 -0
- metadata +187 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
module YammerApi
|
2
|
+
class Client
|
3
|
+
include Api::Feed
|
4
|
+
include Api::Messages
|
5
|
+
include Api::Likes
|
6
|
+
include Api::Users
|
7
|
+
include Request
|
8
|
+
|
9
|
+
def initialize(options={})
|
10
|
+
@consumer_key = options[:consumer_key]
|
11
|
+
@consumer_secret = options[:consumer_key]
|
12
|
+
@auth_token = options[:oauth_token]
|
13
|
+
@consumer_options = options[:oauth_options] || {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def consumer
|
17
|
+
@consumer ||= ::OAuth2::Client.new(@consumer_key, @consumer_secret, @consumer_options.merge(DEFAULT_OAUTH_OPTIONS))
|
18
|
+
end
|
19
|
+
|
20
|
+
def access_token
|
21
|
+
@access_token ||= ::OAuth2::AccessToken.new(consumer, @auth_token)
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
DEFAULT_OAUTH_OPTIONS = {
|
26
|
+
:site => 'https://www.yammer.com',
|
27
|
+
:authorize_url => '/dialog/oauth',
|
28
|
+
:token_url => '/oauth2/access_token.json'
|
29
|
+
}
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module YammerApi
|
2
|
+
module Errors
|
3
|
+
class Error < StandardError
|
4
|
+
attr_reader :data
|
5
|
+
def initialize(data)
|
6
|
+
@data = data
|
7
|
+
super
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# Raised when Yammer returns the HTTP status code 400
|
12
|
+
class BadRequest < Error; end
|
13
|
+
|
14
|
+
# Raised when Yammer returns the HTTP status code 401
|
15
|
+
class Unauthorized < Error; end
|
16
|
+
|
17
|
+
# Raised when Yammer returns the HTTP status code 403
|
18
|
+
class Forbidden < Error; end
|
19
|
+
|
20
|
+
# Raised when Yammer returns the HTTP status code 404
|
21
|
+
class NotFound < Error; end
|
22
|
+
|
23
|
+
# Raised when Yammer returns the HTTP status code 406
|
24
|
+
class NotAcceptable < Error; end
|
25
|
+
|
26
|
+
# Raised when Yammer returns the HTTP status code 500
|
27
|
+
class InternalServerError < Error; end
|
28
|
+
|
29
|
+
# Raised when Yammer returns the HTTP status code 502
|
30
|
+
class BadGateway < Error; end
|
31
|
+
|
32
|
+
# Raised when Yammer returns the HTTP status code 503
|
33
|
+
class ServiceUnavailable < Error; end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module YammerApi
|
2
|
+
class Post < YammerApi::Base
|
3
|
+
lazy_attr_reader :attachment, :client_url, :id, :message_type, :network_id,
|
4
|
+
:posted_at, :recipient, :replied_to_id, :sender_id, :text, :web_url
|
5
|
+
|
6
|
+
# @return Hashie::Mash
|
7
|
+
def attachment
|
8
|
+
attachment = @attrs['attachments'].first
|
9
|
+
if attachment
|
10
|
+
if attachment['type'] == "image"
|
11
|
+
@attachment ||= Mash.new(type: "image", id: attachment["id"], image_url: attachment.fetch("image", {"url" => ""}).fetch("url"))
|
12
|
+
else
|
13
|
+
@attachment ||= Mash.new(type: attachment['type'], name: attachment['name'], id: attachment["id"], image_url: attachment["large_icon_url"], url: attachment["download_url"])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return Time
|
19
|
+
def posted_at
|
20
|
+
#puts @attrs['created_at']
|
21
|
+
@posted_at ||= Time.parse(@attrs['created_at']).utc unless @attrs['created_at'].nil?
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return String
|
25
|
+
def text
|
26
|
+
@text ||= @attrs['body']['plain'] if @attrs['body'] && @attrs['body']['plain']
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return YammerApi::User
|
30
|
+
def user
|
31
|
+
@user ||= YammerApi::User.new(@attrs['sender']) if @attrs['sender']
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return YammerApi::User
|
35
|
+
def recipient
|
36
|
+
@recipient ||= YammerApi::User.new(@attrs['recipient']) if @attrs['recipient']
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module YammerApi
|
4
|
+
|
5
|
+
module Request
|
6
|
+
|
7
|
+
|
8
|
+
DEFAULT_HEADERS = {
|
9
|
+
:headers => {"Content-Type" => "application/json"}
|
10
|
+
}
|
11
|
+
|
12
|
+
API_PATH = '/api/v1'
|
13
|
+
|
14
|
+
protected
|
15
|
+
|
16
|
+
def get(path, options={})
|
17
|
+
response = access_token.get("#{API_PATH}#{path}", DEFAULT_HEADERS.merge(options))
|
18
|
+
raise_errors(response)
|
19
|
+
Mash.from_json(response.body)
|
20
|
+
end
|
21
|
+
|
22
|
+
def post(path, body, options={})
|
23
|
+
response = access_token.post("#{API_PATH}#{path}", DEFAULT_HEADERS.merge(options).merge({:body => body}))
|
24
|
+
raise_errors(response)
|
25
|
+
Mash.from_json(response.body) if response.body
|
26
|
+
end
|
27
|
+
|
28
|
+
def put(path, options={})
|
29
|
+
response = access_token.put("#{API_PATH}#{path}", DEFAULT_HEADERS.merge(options))
|
30
|
+
raise_errors(response)
|
31
|
+
response.body
|
32
|
+
end
|
33
|
+
|
34
|
+
def delete(path, options={})
|
35
|
+
response = access_token.delete("#{API_PATH}#{path}", DEFAULT_HEADERS.merge(options))
|
36
|
+
raise_errors(response)
|
37
|
+
response
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def raise_errors(response)
|
43
|
+
OAuth2::Response
|
44
|
+
case response.status.to_i
|
45
|
+
when 400
|
46
|
+
raise YammerApi::Errors::BadRequest.new("(#{response.code}): #{response.message}")
|
47
|
+
when 401
|
48
|
+
raise YammerApi::Errors::Unauthorized.new("(#{response.code}): #{response.message}")
|
49
|
+
when 403
|
50
|
+
raise YammerApi::Errors::Forbidden.new("(#{response.code}): #{response.message}")
|
51
|
+
when 404
|
52
|
+
raise YammerApi::Errors::NotFound.new("(#{response.code}): #{response.message}")
|
53
|
+
when 406
|
54
|
+
raise YammerApi::Errors::NotAcceptable.new("(#{response.code}): #{response.message}")
|
55
|
+
when 500
|
56
|
+
raise YammerApi::Errors::InternalServerError.new("(#{response.code}): #{response.message}")
|
57
|
+
when 502
|
58
|
+
raise YammerApi::Errors::BadGateway.new("(#{response.code}): #{response.message}")
|
59
|
+
when 503
|
60
|
+
raise YammerApi::Errors::ServiceUnavailable.new("(#{response.code}): #{response.message}")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def to_query(options)
|
65
|
+
options.inject([]) do |collection, opt|
|
66
|
+
collection << "#{opt[0]}=#{opt[1]}"
|
67
|
+
collection
|
68
|
+
end * '&'
|
69
|
+
end
|
70
|
+
|
71
|
+
def to_uri(path, options)
|
72
|
+
uri = URI.parse(path)
|
73
|
+
|
74
|
+
if options && options != {}
|
75
|
+
uri.query = to_query(options)
|
76
|
+
end
|
77
|
+
uri.to_s
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module YammerApi
|
2
|
+
class User < YammerApi::Base
|
3
|
+
|
4
|
+
lazy_attr_reader :full_name, :id, :job_title, :nickname,
|
5
|
+
:profile_url, :profile_image, :stats
|
6
|
+
|
7
|
+
|
8
|
+
# @return String
|
9
|
+
def nickname
|
10
|
+
@nickname ||= @attrs["name"] if @attrs["name"]
|
11
|
+
end
|
12
|
+
|
13
|
+
# @return String
|
14
|
+
def profile_url
|
15
|
+
@profile_url ||= @attrs["web_url"] if @attrs["web_url"]
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return String
|
19
|
+
def profile_image
|
20
|
+
@profile_image ||= @attrs["mugshot_url"] if @attrs["mugshot_url"]
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe YammerApi::Client do
|
4
|
+
before do
|
5
|
+
client.stub(:consumer).and_return(consumer)
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:client) {YammerApi::Client.new(:consumer_key => "consumer_key", :consumer_secret => "consumer_secret", :oauth_token => "oauth_token")}
|
9
|
+
let(:consumer){OAuth2::Client.new('token', 'secret', {:site => 'https://yammer.com'})}
|
10
|
+
|
11
|
+
describe "User's network feed" do
|
12
|
+
|
13
|
+
it "client should get users feed" do
|
14
|
+
stub_http_request(:get, /https:\/\/yammer.com\/api\/v1\/messages.*/).
|
15
|
+
to_return(:body => "{}")
|
16
|
+
posts = client.messages
|
17
|
+
posts.length.should == 0
|
18
|
+
posts.should be_an_instance_of(Array)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "returned array should contain posts" do
|
22
|
+
stub_http_request(:get, /https:\/\/yammer.com\/api\/v1\/messages.*/).
|
23
|
+
to_return(:body => fixture("network_feed.json"))
|
24
|
+
|
25
|
+
posts = client.messages
|
26
|
+
|
27
|
+
posts.length.should == 18
|
28
|
+
posts.first.should be_an_instance_of(YammerApi::Post)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "User's private messages" do
|
34
|
+
|
35
|
+
|
36
|
+
it "returned array should contain posts" do
|
37
|
+
stub_http_request(:get, /https:\/\/yammer.com\/api\/v1\/messages\/private.*/).
|
38
|
+
to_return(:body => fixture("private.json"))
|
39
|
+
|
40
|
+
posts = client.direct_messages
|
41
|
+
|
42
|
+
posts.length.should == 1
|
43
|
+
posts.first.should be_an_instance_of(YammerApi::Post)
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "Posting messages" do
|
49
|
+
it "should be possible to post message" do
|
50
|
+
stub_http_request(:post, /https:\/\/yammer.com\/api\/v1\/messages.*/).
|
51
|
+
to_return(:body => fixture("newly_posted.json"))
|
52
|
+
|
53
|
+
post = client.update("OHAI")
|
54
|
+
post.should be_an_instance_of(YammerApi::Post)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should be possible to post direct message" do
|
58
|
+
stub_http_request(:post, /https:\/\/yammer.com\/api\/v1\/messages.*/).
|
59
|
+
to_return(:body => fixture("newly_posted.json"))
|
60
|
+
|
61
|
+
post = client.send_direct_message("OHAI", "123")
|
62
|
+
post.should be_an_instance_of(YammerApi::Post)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe YammerApi::Post do
|
4
|
+
before do
|
5
|
+
@fixture = MultiJson.decode(fixture "single_post.json")
|
6
|
+
@post = YammerApi::Post.new(@fixture)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should contain correct posting date" do
|
10
|
+
@post.posted_at.should == Time.parse(@fixture["created_at"]).utc
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should contain correct text" do
|
14
|
+
@post.text.should == @fixture["body"]["plain"]
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should have attachment" do
|
18
|
+
@post.attachment.should be_an_instance_of(YammerApi::Mash)
|
19
|
+
@post.attachment.type.should == "image"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should have sender" do
|
23
|
+
@post.user.should be_an_instance_of(YammerApi::User)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe YammerApi::User do
|
4
|
+
before do
|
5
|
+
@fixture = MultiJson.decode(fixture "single_user.json")
|
6
|
+
@user = YammerApi::User.new(@fixture)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should contain correct user id" do
|
10
|
+
@user.id.should == @fixture["id"]
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should contain correct user name" do
|
14
|
+
@user.full_name.should == @fixture["full_name"]
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should contain correct user nickname" do
|
18
|
+
@user.nickname.should == @fixture["name"]
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should contain correct user profile image" do
|
22
|
+
@user.profile_image.should == @fixture["mugshot_url"]
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should contain correct user profile url" do
|
26
|
+
@user.profile_url.should == @fixture["web_url"]
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
{
|
2
|
+
"messages": [
|
3
|
+
{
|
4
|
+
"message_type": "update",
|
5
|
+
"liked_by": {
|
6
|
+
"count": 0,
|
7
|
+
"names": []
|
8
|
+
},
|
9
|
+
"created_at": "2011/02/12 02:41:14 +0000",
|
10
|
+
"thread_id": 78654647,
|
11
|
+
"url": "https://www.yammer.com/api/v1/messages/78654647",
|
12
|
+
"network_id": 104604,
|
13
|
+
"body": {
|
14
|
+
"plain": "Here's a message with a Topic Application.",
|
15
|
+
"parsed": "Here's a message with a Topic Application."
|
16
|
+
},
|
17
|
+
"privacy": "public",
|
18
|
+
"client_url": "https://www.yammer.com/",
|
19
|
+
"sender_type": "user",
|
20
|
+
"id": 78654647,
|
21
|
+
"system_message": false,
|
22
|
+
"attachments": [],
|
23
|
+
"sender_id": 1452329,
|
24
|
+
"replied_to_id": null,
|
25
|
+
"client_type": "Web",
|
26
|
+
"direct_message": false,
|
27
|
+
"web_url": "https://www.yammer.com/yammerdeveloperstestcommunity/messages/78654647"
|
28
|
+
}
|
29
|
+
],
|
30
|
+
"threaded_extended": {},
|
31
|
+
"meta": {
|
32
|
+
"bookmarked_message_ids": [
|
33
|
+
78654647
|
34
|
+
],
|
35
|
+
"current_user_id": 4022984,
|
36
|
+
"feed_name": "Interesting",
|
37
|
+
"followed_user_ids": [
|
38
|
+
1452329
|
39
|
+
],
|
40
|
+
"show_billing_banner": false,
|
41
|
+
"requested_poll_interval": 60,
|
42
|
+
"feed_desc": "Messages in topic Interesting",
|
43
|
+
"ymodules": [],
|
44
|
+
"favorite_message_ids": [
|
45
|
+
78654647
|
46
|
+
],
|
47
|
+
"realtime": {
|
48
|
+
"channel_id": "phxfy",
|
49
|
+
"authentication_token": "sev3eD8glyU+WgtixBMeFtJCcQec7HtgG+lgZW37Tvp4nKtWKi1OLVKyMjEwMrK0MNFRykstKc8vylayMjQwMTMACqRWFGQWVQL5xgaGxiaWBpYWtQCdvw7X",
|
50
|
+
"uri": "https://85.rt.yammer.com/cometd/"
|
51
|
+
}
|
52
|
+
},
|
53
|
+
"references": [
|
54
|
+
{
|
55
|
+
"type": "user",
|
56
|
+
"stats": {
|
57
|
+
"updates": 4,
|
58
|
+
"following": 2,
|
59
|
+
"followers": 1
|
60
|
+
},
|
61
|
+
"url": "https://www.yammer.com/api/v1/users/1452329",
|
62
|
+
"mugshot_url": "https://assets1.yammer.com/user_uploaded/photos/p1/0141/2640/n1644278019_46479_62_small.jpg",
|
63
|
+
"full_name": "Matt Knopp",
|
64
|
+
"job_title": null,
|
65
|
+
"state": "active",
|
66
|
+
"name": "mknopp",
|
67
|
+
"web_url": "https://www.yammer.com/yammerdeveloperstestcommunity/users/mknopp",
|
68
|
+
"id": 1452329
|
69
|
+
},
|
70
|
+
{
|
71
|
+
"type": "thread",
|
72
|
+
"topics": [
|
73
|
+
{
|
74
|
+
"type": "topic",
|
75
|
+
"id": 712836
|
76
|
+
}
|
77
|
+
],
|
78
|
+
"thread_starter_id": 78654647,
|
79
|
+
"has_attachments": false,
|
80
|
+
"stats": {
|
81
|
+
"first_reply_at": null,
|
82
|
+
"latest_reply_at": "2011/02/12 02:41:14 +0000",
|
83
|
+
"updates": 1,
|
84
|
+
"latest_reply_id": 78654647,
|
85
|
+
"first_reply_id": null
|
86
|
+
},
|
87
|
+
"url": "https://www.yammer.com/api/v1/messages/in_thread/78654647",
|
88
|
+
"privacy": "public",
|
89
|
+
"direct_message": false,
|
90
|
+
"web_url": "https://www.yammer.com/yammerdeveloperstestcommunity#/Threads/show?threadId=78654647",
|
91
|
+
"id": 78654647
|
92
|
+
},
|
93
|
+
{
|
94
|
+
"type": "topic",
|
95
|
+
"url": "https://www.yammer.com/api/v1/topics/712836",
|
96
|
+
"normalized_name": "interesting",
|
97
|
+
"name": "Interesting",
|
98
|
+
"permalink": "interesting",
|
99
|
+
"web_url": "https://www.yammer.com/yammerdeveloperstestcommunity/topics/712836",
|
100
|
+
"id": 712836
|
101
|
+
}
|
102
|
+
]
|
103
|
+
}
|