baloo 0.1

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 ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in baloo.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 John Butler
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # Baloo
2
+
3
+ The simple 'bear' necessities for working with graph.facebook.com
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'baloo'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install baloo
18
+
19
+ ## Usage
20
+
21
+ ```ruby
22
+ # configure
23
+ # only required if you're going to do stuff with your app access token later
24
+ Baloo.configure :app_id => '...', :app_secret => '...', app_namespace => '...'
25
+
26
+ #get /me
27
+ Baloo.get 'me', :query => {:access_token => '...'}
28
+ # => {...} # a facebook user hash
29
+
30
+ # post
31
+ Baloo.post 'me/albums', :body => {:access_token => '...', :name => 'Baloo Album'}
32
+ # => {"id": "..."}
33
+
34
+ # app access token / client credentials
35
+ # Baloo#app_token is an alias for Baloo#client_credentials
36
+ Baloo.app_token
37
+ # => "your_app_token"
38
+
39
+ Baloo.client_credentials
40
+ # => "same_thing"
41
+
42
+ Baloo.app_token(app_id, app_secret)
43
+ # => "app token for some other app"
44
+
45
+ # Batch Requests
46
+ batch = Baloo::BatchRequest.new
47
+ 25.times { batch.add :get, 'betapond' }
48
+ batch.perform {|res| puts res['body']['id'] }
49
+ # => 158724218692 (25 times)
50
+ ```
51
+
52
+ ## Contributing
53
+
54
+ 1. Fork it
55
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
56
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
57
+ 4. Push to the branch (`git push origin my-new-feature`)
58
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/baloo.gemspec ADDED
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/baloo/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["John Butler"]
6
+ gem.email = ["johnnypez@gmail.com"]
7
+ gem.description = %q{The simple 'bear' necessities for working with graph.facebook.com}
8
+ gem.summary = %q{A simple Facebook Graph client}
9
+ gem.homepage = ""
10
+
11
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ gem.files = `git ls-files`.split("\n")
13
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ gem.name = "baloo"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Baloo::VERSION
17
+
18
+ gem.add_dependency "httparty"
19
+ gem.add_dependency "activesupport"
20
+ end
@@ -0,0 +1,41 @@
1
+ require 'yajl'
2
+ module Baloo
3
+ class BatchRequest
4
+
5
+ Limit = 20
6
+
7
+ attr_accessor :requests, :responses
8
+
9
+ def initialize
10
+ @requests = []
11
+ @responses = []
12
+ end
13
+
14
+ def add(method, path, body = {})
15
+ request = { :method => method, :relative_url => path }
16
+ unless body.empty?
17
+ request[:body] = HTTParty::HashConversions.to_params(body)
18
+ end
19
+ @requests << request
20
+ end
21
+
22
+ # peform the batch request
23
+ # the passed block will recieve each response as it is parsed
24
+ def perform(&block)
25
+ raise Exception.new("You must have at least 2 requests") unless @requests.length > 1
26
+ @responses.clear
27
+ requests.each_slice(Limit).to_a.each do |batch|
28
+ body = {
29
+ :batch => Yajl::Encoder.encode(batch),
30
+ :access_token => Baloo.client_credentials
31
+ }
32
+ Client.post("/", :body => body).each do |response|
33
+ # response['headers'] = Yajl::Parser.parse(response['headers'])
34
+ response['body'] = Yajl::Parser.parse(response['body'])
35
+ yield response
36
+ end
37
+ end
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,27 @@
1
+ module Baloo
2
+ class Client
3
+ include HTTParty
4
+
5
+ base_uri "https://graph.facebook.com"
6
+ parser Parser
7
+ format :plain
8
+
9
+ private
10
+ # overrides HTTParty#perform_request to handle exceptions and http errors
11
+ def self.perform_request(http_method, path, options, &block) #:nodoc:
12
+ response = super
13
+ case response.response
14
+ when Net::HTTPSuccess
15
+ response
16
+ when Net::HTTPClientError, Net::HTTPServerError
17
+ raise HTTPError.new(response)
18
+ else
19
+ # unknown http error, raise it
20
+ response.response.error!
21
+ end
22
+
23
+ rescue Net::ProtocolError, Timeout::Error, Errno::ETIMEDOUT, Errno::ECONNRESET
24
+ raise NetworkError.new
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,21 @@
1
+ module Baloo
2
+ module Convenience
3
+
4
+ # get an app access token
5
+ def client_credentials(id = Baloo.app_id, secret = Baloo.app_secret)
6
+ @stored_client_credentials ||= {}
7
+ unless @stored_client_credentials[id]
8
+ params = {
9
+ :client_id => id,
10
+ :client_secret => secret,
11
+ :grant_type => 'client_credentials'
12
+ }
13
+ @stored_client_credentials[id] = get('oauth/access_token', :query => params).split("=")[1]
14
+ end
15
+
16
+ @stored_client_credentials[id]
17
+ end
18
+ alias :app_token :client_credentials
19
+
20
+ end
21
+ end
@@ -0,0 +1,29 @@
1
+ module Baloo
2
+
3
+ class Error < StandardError
4
+ end
5
+
6
+ class HTTPError < Error
7
+ attr_reader :response
8
+ MessageFormat = "%s %s => %s \n %s"
9
+
10
+ def initialize(response)
11
+ @response = response
12
+ super sprintf(MessageFormat, response.request.http_method, response.request.uri, response.response.class, response.body)
13
+ end
14
+ end
15
+
16
+ class NetworkError < Error
17
+ attr_reader :original
18
+
19
+ def initialize(original = $!)
20
+ if original.nil?
21
+ super
22
+ else
23
+ super(original.message)
24
+ end
25
+ @original = original
26
+ end
27
+ end
28
+
29
+ end
@@ -0,0 +1,23 @@
1
+ require 'yajl'
2
+ module Baloo
3
+ class Parser < HTTParty::Parser
4
+
5
+ def parse
6
+ if /^true|false$/.match(body)
7
+ bool
8
+ elsif /^\{|\[.+\}|\]$/.match(body)
9
+ json
10
+ else
11
+ body
12
+ end
13
+ end
14
+
15
+ def json
16
+ Yajl::Parser.parse(body)
17
+ end
18
+
19
+ def bool
20
+ body =~ /^true$/ ? true : false
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,3 @@
1
+ module Baloo
2
+ VERSION = "0.1"
3
+ end
data/lib/baloo.rb ADDED
@@ -0,0 +1,50 @@
1
+ require "active_support/core_ext"
2
+ require "httparty"
3
+
4
+ require "baloo/error"
5
+ require "baloo/parser"
6
+ require "baloo/client"
7
+ require "baloo/version"
8
+ require "baloo/convenience"
9
+ require "baloo/batch_request"
10
+
11
+ module Baloo
12
+
13
+ class << self
14
+
15
+ attr_accessor :app_id
16
+ attr_accessor :app_secret
17
+ attr_accessor :app_namespace
18
+
19
+ include Convenience
20
+
21
+ def configure(options = {})
22
+ options.stringify_keys!
23
+ %w(app_id app_secret app_namespace).each {|opt| send("#{opt}=", options[opt])}
24
+ end
25
+
26
+ %w(get post put delete head).each do |http_method|
27
+ define_method "#{http_method}" do |*args|
28
+ slasherize args
29
+ response = Client.send(http_method, *args)
30
+ if block_given?
31
+ yield response.parsed_response
32
+ else
33
+ response.parsed_response
34
+ end
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ # ensure path starts with a forwardslash
41
+ def slasherize(args)
42
+ if args.first && args.first.is_a?(String)
43
+ args[0] = ("/" << args.first) unless args.first =~ /^\//
44
+ end
45
+
46
+ args
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe Baloo::BatchRequest do
4
+
5
+ it "should bloody well work!" do
6
+ Baloo.configure :app_id => "204876786306406", :app_secret => "34dc50cea8b8bbdf1dba1018c9aebc90", :app_namespace => "baloo_test"
7
+
8
+ batch = Baloo::BatchRequest.new
9
+ batch.add :get, '582470824'
10
+ batch.add :post, '582470824/albums', :name => "Foo Album"
11
+ 25.times { batch.add :get, 'betapond' }
12
+
13
+ responses = []
14
+ batch.perform do |response|
15
+ responses << response
16
+ response['code'].class.should eq Fixnum
17
+ end
18
+
19
+ responses.count.should eq 27
20
+ responses[0]['body'].class.should eq Hash
21
+ responses[0]['headers'].class.should eq Array
22
+
23
+ responses[0]['body']['username'].should eq 'johnnypez'
24
+ responses[1]['code'].should eq 400 # no access token was give so Bad Request is expected
25
+ responses[3]['code'].should eq 200
26
+ end
27
+
28
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe Baloo do
4
+
5
+ it "should allow configuration for a fb app" do
6
+ Baloo.app_id.should be nil
7
+ Baloo.app_secret.should be nil
8
+ Baloo.app_namespace.should be nil
9
+
10
+ Baloo.configure :app_id => 1, :app_secret => 2, :app_namespace => "test"
11
+
12
+ Baloo.app_id.should eq 1
13
+ Baloo.app_secret.should eq 2
14
+ Baloo.app_namespace.should eq "test"
15
+ end
16
+
17
+ it "should allow starting forwardslash or not" do
18
+ res = Baloo.get 'theo2'
19
+ res.class.should eq Hash
20
+ Baloo.get(res['id'])['id'].should eq res['id']
21
+ Baloo.get('/theo2')['id'].should eq res['id']
22
+ end
23
+
24
+ it "should allow t/f in the response" do
25
+ res = Baloo.get 'boylesports'
26
+ res.class.should eq FalseClass
27
+ end
28
+
29
+ it "should handle errors like a boss!" do
30
+ expect { Baloo.get 'me' }.to raise_error Baloo::HTTPError
31
+ end
32
+
33
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe Baloo::Convenience do
4
+
5
+ it "should support retrieval of app access tokens" do
6
+ Baloo.configure :app_id => "204876786306406", :app_secret => "34dc50cea8b8bbdf1dba1018c9aebc90", :app_namespace => "baloo_test"
7
+ Baloo.client_credentials.should match(/^204876786306406\|.+/)
8
+ end
9
+
10
+ end
@@ -0,0 +1,13 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper.rb"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+ end
12
+
13
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/baloo")
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: baloo
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - John Butler
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-16 00:00:00.000000000 +01:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: httparty
17
+ requirement: &70121616862160 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *70121616862160
26
+ - !ruby/object:Gem::Dependency
27
+ name: activesupport
28
+ requirement: &70121616861140 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: *70121616861140
37
+ description: The simple 'bear' necessities for working with graph.facebook.com
38
+ email:
39
+ - johnnypez@gmail.com
40
+ executables: []
41
+ extensions: []
42
+ extra_rdoc_files: []
43
+ files:
44
+ - .gitignore
45
+ - .rspec
46
+ - Gemfile
47
+ - LICENSE
48
+ - README.md
49
+ - Rakefile
50
+ - baloo.gemspec
51
+ - lib/baloo.rb
52
+ - lib/baloo/batch_request.rb
53
+ - lib/baloo/client.rb
54
+ - lib/baloo/convenience.rb
55
+ - lib/baloo/error.rb
56
+ - lib/baloo/parser.rb
57
+ - lib/baloo/version.rb
58
+ - spec/batch_request_spec.rb
59
+ - spec/client_spec.rb
60
+ - spec/convenience_spec.rb
61
+ - spec/spec_helper.rb
62
+ has_rdoc: true
63
+ homepage: ''
64
+ licenses: []
65
+ post_install_message:
66
+ rdoc_options: []
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ! '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ! '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubyforge_project:
83
+ rubygems_version: 1.6.2
84
+ signing_key:
85
+ specification_version: 3
86
+ summary: A simple Facebook Graph client
87
+ test_files:
88
+ - spec/batch_request_spec.rb
89
+ - spec/client_spec.rb
90
+ - spec/convenience_spec.rb
91
+ - spec/spec_helper.rb