diff --git a/README.md b/README.md index 277c1ae..9e3542d 100644 --- a/README.md +++ b/README.md @@ -10,17 +10,45 @@ Installation ------------ gem install yammer -What's in 0.1.2? +What's in 0.1.4? ---------------- -This release offers some additional API support thanks to [ybenjo](https://github.com/ybenjo), eg suggestions, search and groups. +This release rips old the old api dependencies on Faraday and whatever else handles connection related issues and passed it all off to Yammer's own Yam gem(which itself uses Faraday). -We still only offer the most basic support for [Yammer's REST API](https://developer.yammer.com/api/). -This gem is **far** from finished or offering complete coverage of all the API methods offered by Yammer. It's our first release covering our basic needs to hook into the messages API. +Improved api support -We are releasing this early version in order to share the path we have taken, offer the community a new Ruby Gem to interact with the Yammer API and build upon it with more support of others that might find it useful. + yam.users + yam.in_group + +Better Exception Handling + + It was completely broken, now you can catch all sorts of exceptions with Yammer api based upon http status: + + - 400: Yammer::BadRequest + - 401: Yammer::Unauthorized + - 403: Yammer::Forbidden + - 404: Yammer::NotFound + - 406: Yammer::NotAcceptable + - 500: Yammer:InternalServerError + - 502: Yammer::BadGateway + - 503: Yammer::ServiceUnavailable + + +Getting Started +--------------- + +You should probably be using Omniauth(http://github.com/intridea/omniauth), cuz its awesome, and be following that flow. Ryan Bate's excellent RailsCasts are also a great reference: http://railscasts.com/episodes/236-omniauth-part-2 + +Whatever controller handles the callback, you will have access to a "credentials" key in the oauth object which has an "expires" key, and a "token" key. I stash that entire object in a serialized string in my Authentication model. This token is what you will need. + + token = current_user.authentications.find_by_provider("yammer").credentials.token + yam = Yammer.new(oauth_token: token) + +That's it! + + yam.groups + yam.users -I am eternally grateful for the work that the team that created the awesome (did I say how awesome that Gem is already? ;) ) [Twitter](https://github.com/jnunemaker/twitter) Ruby Gem put into it and made it open and free. **THANK YOU** :) TODO ---- @@ -76,4 +104,4 @@ Submitting a Pull Request Copyright --------- Copyright (c) 2011, Bruno Mattarollo -See [LICENSE](https://github.com/roadly/yammer/blob/master/LICENSE.md) for details. \ No newline at end of file +See [LICENSE](https://github.com/roadly/yammer/blob/master/LICENSE.md) for details. diff --git a/lib/yammer.rb b/lib/yammer.rb index 60d4498..82fb0c8 100644 --- a/lib/yammer.rb +++ b/lib/yammer.rb @@ -1,3 +1,4 @@ +require 'yam' require 'yammer/api' require 'yammer/client' require 'yammer/configuration' diff --git a/lib/yammer/authentication.rb b/lib/yammer/authentication.rb index 5a6f226..2e9c105 100644 --- a/lib/yammer/authentication.rb +++ b/lib/yammer/authentication.rb @@ -1,6 +1,13 @@ module Yammer # @private module Authentication + # Check whether user is authenticated + # + # @return [Boolean] + def authenticated? + authentication.values.all? + end + private # Authentication hash @@ -8,18 +15,9 @@ module Authentication # @return [Hash] def authentication { - :consumer_key => consumer_key, - :consumer_secret => consumer_secret, - :token => oauth_token, - :token_secret => oauth_token_secret, + oauth_token: oauth_token } end - # Check whether user is authenticated - # - # @return [Boolean] - def authenticated? - authentication.values.all? - end end end diff --git a/lib/yammer/client.rb b/lib/yammer/client.rb index 011a912..839bc3d 100644 --- a/lib/yammer/client.rb +++ b/lib/yammer/client.rb @@ -13,6 +13,7 @@ class Client < API require 'yammer/client/search' require 'yammer/client/suggestions' require 'yammer/client/groups' + require 'yammer/client/activity' alias :api_endpoint :endpoint @@ -22,5 +23,6 @@ class Client < API include Yammer::Client::Search include Yammer::Client::Suggestions include Yammer::Client::Groups + include Yammer::Client::Activity end end diff --git a/lib/yammer/client/activity.rb b/lib/yammer/client/activity.rb new file mode 100644 index 0000000..ee01049 --- /dev/null +++ b/lib/yammer/client/activity.rb @@ -0,0 +1,9 @@ +module Yammer + class Client + module Activity + def new_activity(options={}) + response = post('activity', options) + end + end + end +end \ No newline at end of file diff --git a/lib/yammer/client/users.rb b/lib/yammer/client/users.rb index b461658..3f41841 100644 --- a/lib/yammer/client/users.rb +++ b/lib/yammer/client/users.rb @@ -5,6 +5,27 @@ module Users def find_by_id(id, options={}) response = get("users/#{id}", options, :json) end + + def users(options={}) + response = get("users", options, :json) + end + + def in_group(group_id, options={}) + response = get("users/in_group/#{group_id}", options, :json) + end + + def current(options={}) + response = get("users/current", options, :json) + end + + def followers(name, options={}) + response = get("users/following/#{name}", options, :json) + end + + def following(email, options={}) + response = get("users/by_email?email=#{email}", options, :json) + end + end end end diff --git a/lib/yammer/configuration.rb b/lib/yammer/configuration.rb index bb53a3b..67c1766 100644 --- a/lib/yammer/configuration.rb +++ b/lib/yammer/configuration.rb @@ -6,25 +6,16 @@ module Configuration # An array of valid keys in the options hash when configuring a {Yammer::API} VALID_OPTIONS_KEYS = [ :adapter, - :consumer_key, - :consumer_secret, :endpoint, :format, :gateway, :oauth_token, - :oauth_token_secret, :proxy, :user_agent].freeze # The adapter that will be used to connect if none is set DEFAULT_ADAPTER = :net_http - # By default, don't set an application key - DEFAULT_CONSUMER_KEY = nil - - # By default, don't set an application secret - DEFAULT_CONSUMER_SECRET = nil - # The endpoint that will be used to connect if none is set # # @note This is configurable in case you want to use HTTP instead of HTTPS, specify a different API version. @@ -38,9 +29,6 @@ module Configuration # By default, don't set a user oauth token DEFAULT_OAUTH_TOKEN = nil - # By default, don't set a user oauth secret - DEFAULT_OAUTH_TOKEN_SECRET = nil - # By default, don't use a proxy server DEFAULT_PROXY = nil @@ -72,12 +60,9 @@ def options # Reset all configuration options to defaults def reset self.adapter = DEFAULT_ADAPTER - self.consumer_key = DEFAULT_CONSUMER_KEY - self.consumer_secret = DEFAULT_CONSUMER_SECRET self.endpoint = DEFAULT_ENDPOINT self.format = DEFAULT_FORMAT self.oauth_token = DEFAULT_OAUTH_TOKEN - self.oauth_token_secret = DEFAULT_OAUTH_TOKEN_SECRET self.proxy = DEFAULT_PROXY self.user_agent = DEFAULT_USER_AGENT self.gateway = DEFAULT_GATEWAY diff --git a/lib/yammer/connection.rb b/lib/yammer/connection.rb index 580eb0a..421cc15 100644 --- a/lib/yammer/connection.rb +++ b/lib/yammer/connection.rb @@ -1,44 +1,10 @@ -require 'faraday_middleware' -require 'faraday/request/multipart_with_file' -require 'faraday/request/gateway' -require 'faraday/request/yammer_oauth' -require 'faraday/response/raise_http_4xx' -require 'faraday/response/raise_http_5xx' - module Yammer # @private module Connection private def connection(format=format) - options = { - :headers => { - :accept => "application/#{format}", - :user_agent => user_agent, - }, - :proxy => proxy, - :ssl => {:verify => false}, - :url => api_endpoint, - } - - Faraday.new(options) do |builder| - builder.use Faraday::Request::MultipartWithFile - builder.use Faraday::Request::YammerOAuth, authentication if authenticated? - builder.use Faraday::Request::Multipart - builder.use Faraday::Request::UrlEncoded - builder.use Faraday::Request::Gateway, gateway if gateway - builder.use Faraday::Response::RaiseHttp4xx - case format.to_s.downcase - when 'json' - builder.use Faraday::Response::Mashify - builder.use Faraday::Response::ParseJson - when 'xml' - builder.use Faraday::Response::Mashify - builder.use Faraday::Response::ParseXml - end - builder.use Faraday::Response::RaiseHttp5xx - builder.adapter(adapter) - end + Yam.new(oauth_token, endpoint) end end end diff --git a/lib/yammer/error.rb b/lib/yammer/error.rb index 3d882b1..3c8b696 100644 --- a/lib/yammer/error.rb +++ b/lib/yammer/error.rb @@ -1,4 +1,52 @@ module Yammer + + # This gem seems to monkey patch faraday to catch certain exceptions + # and even that attempt does not seem to be loaded anywhere, so instead + # we'll catch the error on every request(and possibly elsewhere) + # and then pass the exception to this class who will figure out the proper + # high level exception to raise + class ErrorProxy + def self.new(exception) + return self.determine_exception(exception) + end + + def self.determine_exception(exception) + exception = exception + message = exception.message + status = exception.response[:status] + headers = exception.response[:headers] + + case status.to_i + when 400 + Yammer::BadRequest.new(error_message(message), headers) + when 401 + Yammer::Unauthorized.new(error_message(message), headers) + when 403 + Yammer::Forbidden.new(error_message(message), headers) + when 404 + Yammer::NotFound.new(error_message(message), headers) + when 429 + Yammer::TooManyRequests.new(error_message(message), headers) + when 406 + Yammer::NotAcceptable.new(error_message(message), headers) + when 500 + Yammer::InternalServerError.new(error_message("Something is technically wrong."), headers) + when 502 + Yammer::BadGateway.new(error_message("Yammer is down or being upgraded."), headers) + when 503 + Yammer::ServiceUnavailable.new(error_message("(__-){ Yammer is over capacity."), headers) + else + Exception.new("Unhandled Exception Status: #{status} - #{message}") + end + end + + private + def self.error_message(msg) + #TODO: this can be used in the future to print nicer messages + msg + end + end + # Custom error class for rescuing from all Yammer errors class Error < StandardError attr_reader :http_headers @@ -48,4 +96,7 @@ class BadGateway < Error; end # Raised when Yammer returns the HTTP status code 503 class ServiceUnavailable < Error; end + + # Raised when you hit Yammer's request rate limit + class TooManyRequests < Error;end end diff --git a/lib/yammer/request.rb b/lib/yammer/request.rb index 873c553..41f8a8b 100644 --- a/lib/yammer/request.rb +++ b/lib/yammer/request.rb @@ -26,22 +26,31 @@ def delete(path, options={}, format=format) # Perform an HTTP request def request(method, path, options, format) begin - response = connection(format).send(method) do |request| - case method.to_sym - when :get, :delete - request.url(formatted_path(path, format), options) - when :post, :put - request.path = formatted_path(path, format) - request.body = options unless options.empty? - end - end - 'raw' == format.to_s.downcase ? response : response.body + case method.to_sym + when :get, :delete + response = connection.send(method, formatted_path(path, format), options) + when :post + response = connection.send(method, formatted_path(path, format), options) + when :put + raise "PUT verbs are not yet supported!" + # request.path = formatted_path(path, format) + # request.body = options unless options.empty? + end + + #TODO: format is not obeyed. From Yam we get back an array of objects + response + rescue MultiJson::DecodeError Hashie::Mash.new + rescue Faraday::Error::ClientError => e + raise Yammer::ErrorProxy.new(e) + end end def formatted_path(path, format) + #paths must have a leading / + path = "/#{path}" if path[0] != "/" case format.to_s.downcase when 'json', 'xml' [path, format].compact.join('.') diff --git a/lib/yammer/version.rb b/lib/yammer/version.rb index 35f60b4..50e4359 100644 --- a/lib/yammer/version.rb +++ b/lib/yammer/version.rb @@ -1,4 +1,4 @@ module Yammer # The version of the gem - VERSION = '0.1.2'.freeze unless defined?(::Yammer::VERSION) + VERSION = '0.1.6'.freeze unless defined?(::Yammer::VERSION) end diff --git a/yammer.gemspec b/yammer.gemspec index d3533a5..b81984b 100644 --- a/yammer.gemspec +++ b/yammer.gemspec @@ -3,26 +3,13 @@ $:.push File.expand_path("../lib", __FILE__) require "yammer/version" Gem::Specification.new do |gem| - gem.add_development_dependency 'maruku', '~> 0.6' - gem.add_development_dependency 'nokogiri', '~> 1.4' - gem.add_development_dependency 'rake', '~> 0.9' - gem.add_development_dependency 'rspec', '~> 2.6' - gem.add_development_dependency 'simplecov', '~> 0.4' - gem.add_development_dependency 'webmock', '~> 1.6' - gem.add_development_dependency 'yard', '~> 0.7' - gem.add_development_dependency 'ZenTest', '~> 4.5' - gem.add_runtime_dependency 'hashie', '~> 1.0.0' - gem.add_runtime_dependency 'faraday', '~> 0.6.1' - gem.add_runtime_dependency 'faraday_middleware', '~> 0.6.3' - gem.add_runtime_dependency 'multi_json', '~> 1.0.0' - gem.add_runtime_dependency 'multi_xml', '~> 0.2.0' - gem.add_runtime_dependency 'simple_oauth', '~> 0.1.5' - gem.authors = ["Bruno Mattarollo"] + gem.add_runtime_dependency 'yam', '~> 0.0.6' + gem.authors = ["Bruno Mattarollo, Peter Philips"] gem.description = %q{A Ruby wrapper for the Yammer REST API} - gem.email = ['bruno.mattarollo@gmail.com'] + gem.email = ['bruno.mattarollo@gmail.com', 'pete@p373.net'] gem.executables = `git ls-files -- bin/*`.split("\n").map{|f| File.basename(f)} gem.files = `git ls-files`.split("\n") - gem.homepage = 'https://github.com/roadly/yammer' + gem.homepage = 'https://github.com/synth/yammer' gem.name = 'yammer' gem.require_paths = ['lib'] gem.required_rubygems_version = Gem::Requirement.new('>= 1.3.6')