infomeme_client 0.1.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.
Files changed (50) hide show
  1. data/.document +5 -0
  2. data/.gitignore +21 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +8 -0
  5. data/Rakefile +54 -0
  6. data/VERSION +1 -0
  7. data/lib/infomeme_client/base.rb +77 -0
  8. data/lib/infomeme_client/communication.rb +75 -0
  9. data/lib/infomeme_client/entity_hash/comment.rb +2 -0
  10. data/lib/infomeme_client/entity_hash/meme.rb +45 -0
  11. data/lib/infomeme_client/entity_hash/meme_type.rb +2 -0
  12. data/lib/infomeme_client/entity_hash/transaction.rb +3 -0
  13. data/lib/infomeme_client/entity_hash/user.rb +2 -0
  14. data/lib/infomeme_client/entity_hash.rb +65 -0
  15. data/lib/infomeme_client/errors.rb +22 -0
  16. data/lib/infomeme_client/functions/meme.rb +23 -0
  17. data/lib/infomeme_client/functions/user.rb +55 -0
  18. data/lib/infomeme_client/functions/user_meme.rb +94 -0
  19. data/lib/infomeme_client/functions/user_transaction.rb +21 -0
  20. data/lib/infomeme_client/functions.rb +16 -0
  21. data/lib/infomeme_client/meme_application.rb +18 -0
  22. data/lib/infomeme_client/permissions.rb +22 -0
  23. data/lib/infomeme_client/response.rb +51 -0
  24. data/lib/infomeme_client.rb +21 -0
  25. data/test/fixtures/memes/comments.json +1 -0
  26. data/test/fixtures/memes/meme.json +1 -0
  27. data/test/fixtures/memes/memes.json +1 -0
  28. data/test/fixtures/memes/types.json +1 -0
  29. data/test/fixtures/oauth/access_token.json +1 -0
  30. data/test/fixtures/oauth/authorize.json +1 -0
  31. data/test/fixtures/oauth/permissions.json +1 -0
  32. data/test/fixtures/oauth/request_token.json +1 -0
  33. data/test/fixtures/oauth/verify_access.json +1 -0
  34. data/test/fixtures/response/error.json +1 -0
  35. data/test/fixtures/response/ok.json +1 -0
  36. data/test/fixtures/response/test.json +1 -0
  37. data/test/fixtures/response/test_extract.json +1 -0
  38. data/test/fixtures/users/memes.json +1 -0
  39. data/test/fixtures/users/permissions.json +1 -0
  40. data/test/fixtures/users/user.json +1 -0
  41. data/test/fixtures/users/user_public.json +1 -0
  42. data/test/helper.rb +69 -0
  43. data/test/test_authorization.rb +56 -0
  44. data/test/test_communication.rb +46 -0
  45. data/test/test_entity_hash.rb +15 -0
  46. data/test/test_meme_functions.rb +46 -0
  47. data/test/test_permissions.rb +25 -0
  48. data/test/test_user_functions.rb +15 -0
  49. data/test/test_user_meme_functions.rb +47 -0
  50. metadata +164 -0
@@ -0,0 +1,55 @@
1
+ module InfomemeClient::Functions::User
2
+ attr_accessor :default_language, :default_currency
3
+
4
+ def register(email, username, password, firstname, lastname, optional_fields = {})
5
+ optional_fields.set(:language_code, optional_fields.key?(:language) ? optional_fields.delete(:language) : default_language) #language is mandatory
6
+ optional_fields.set(:currency_code, optional_fields.key?(:currency) ? optional_fields.delete(:currency) : default_currency) #currency is mandatory
7
+ handle_response :post, "/users/register", optional_fields.merge({:email => email, :username => username, :password => password, :firstname => firstname, :lastname => lastname}) do
8
+ authorize_with_credentials username, password and return true
9
+ end
10
+ end
11
+
12
+ def user(user_id = nil)
13
+ return false if ! authorized? && user_id.nil?
14
+ extract_from_response :user, :get, "/users/#{user_id || verified_user}"
15
+ end
16
+
17
+ def update_settings(attribs = {})
18
+ return false unless authorized?
19
+ handle_response :put, "/users/#{verified_user}", attribs do
20
+ refresh_settings and return true
21
+ end
22
+ end
23
+
24
+ def confirm(confirm_code)
25
+ return false unless authorized?
26
+ handle_response :put, "/users/#{verified_user}/confirm", {:confirm_code => confirm_code} do
27
+ refresh_settings and return true
28
+ end
29
+ end
30
+
31
+ def confirmed?
32
+ authorized? && settings && settings.confirmed
33
+ end
34
+
35
+ def reset_password(user_id = nil)
36
+ return false if ! authorized? && user_id.nil?
37
+ handle_response :get, "/users/#{user_id || verified_user}/reset_password"
38
+ end
39
+
40
+ def new_password(new_password, user_id = nil, confirm_code = "")
41
+ return false if ! authorized? && user_id.nil?
42
+ handle_response :put, "/users/#{user_id || verified_user}/new_password", {:new_password => new_password}.merge(user_id.nil? ? {} : {:confirm_code => confirm_code})
43
+ end
44
+
45
+ private
46
+ attr_accessor :settings
47
+
48
+ def refresh_settings
49
+ self.settings = nil
50
+ return false unless authorized?
51
+ response = get("/users/#{verified_user}")
52
+ return false if response.error?
53
+ self.settings = response.user
54
+ end
55
+ end
@@ -0,0 +1,94 @@
1
+ module InfomemeClient::Functions::UserMeme
2
+ def library(options = {})
3
+ get_own_memes options
4
+ end
5
+
6
+ def published(options = {})
7
+ get_own_memes options, "published"
8
+ end
9
+
10
+ def inactive(options = {})
11
+ get_own_memes options, "inactive"
12
+ end
13
+
14
+ def incomplete(options = {})
15
+ get_own_memes options, "incomplete"
16
+ end
17
+
18
+ def can_publish?
19
+ authorized? && settings && settings.can_publish
20
+ end
21
+
22
+ def publish(meme_type, options = {})
23
+ return false unless can_publish?
24
+ handle_response :post, "/user/#{verified_user}/memes", options.merge({:meme_type => meme_type.respond_to?(:id) ? meme_type.id : meme_type}) do |resp|
25
+ resp.meme_id unless resp.error?
26
+ end
27
+ end
28
+
29
+ def update_meme(meme_id, options = {})
30
+ meme_function meme_id, :put, nil, options
31
+ end
32
+
33
+ def delete_meme(meme_id)
34
+ meme_function meme_id, :delete
35
+ end
36
+
37
+ def confirm_meme(meme_id)
38
+ meme_function meme_id, :put, "confirm"
39
+ end
40
+
41
+ def activate_meme(meme_id)
42
+ meme_function meme_id, :put, "activate"
43
+ end
44
+
45
+ def deactivate_meme(meme_id)
46
+ meme_function meme_id, :put, "deactivate"
47
+ end
48
+
49
+ def upload_for_meme(meme_id, raw = false)
50
+ return false unless authorized?
51
+ handle_response :get, "/users/#{verified_user}/memes/#{meme_id}/upload_url" do |resp|
52
+ (raw ? res.upload_url : finalize_get_url(resp.upload_url, generate_signature)) unless resp.error?
53
+ end
54
+ end
55
+
56
+ def upload(meme_id, file)
57
+ upload_url = upload_for_meme(meme_id, true)
58
+ if upload_url
59
+ url = URI.parse(upload_url)
60
+ req = Net::HTTP::Post::Multipart.new url.path, generate_signature.merge({:meme_id => meme_id, :file => file})
61
+ resp = Net::HTTP.start(url.host, url.port) {|http| http.request(req)}
62
+ resp == Net::HTTPSuccess
63
+ end
64
+ end
65
+
66
+ def rate(meme_id, rating)
67
+ return false unless authorized?
68
+ handle_response :post, "/users/#{verified_user}/memes/#{meme_id}/rates", {:rating => rating}
69
+ end
70
+
71
+ def comment(meme_id, comment)
72
+ return false unless authorized?
73
+ handle_response :post, "/users/#{verified_user}/memes/#{meme_id}/comments", {:comment => comment}
74
+ end
75
+
76
+ private
77
+ def generate_signature
78
+ nonce = OAuth::Helper.generate_nonce
79
+ timestamp = Time.now.to_i
80
+ req_proxy = OAuth::RequestProxy.proxy("method" => "GET", "uri" => consumer.site, "parameters" => {"oauth_consumer_key" => consumer.key, "oauth_token" => token.token, "oauth_nonce" => nonce, "oauth_timestamp" => timestamp, "oauth_signature_method" => "HMAC-SHA1"})
81
+ signature = req_proxy.sign({:consumer_secret => consumer.secret, :token_secret => token.secret})
82
+ {:oauth_token => token.token, :oauth_nonce => nonce, :oauth_timestamp => timestamp, :oauth_signature => signature}
83
+ end
84
+
85
+ def get_own_memes(options = {}, cmd = nil, headers = {})
86
+ return false unless authorized?
87
+ get_memes("/users/#{verified_user}/memes" + (cmd.nil? ? "" : "/#{cmd}"), options, headers)
88
+ end
89
+
90
+ def meme_function(meme_id, method, cmd = nil, params = {}, headers = {})
91
+ return false unless authorized?
92
+ handle_response method, "/users/#{verified_user}/memes/#{meme_id}" + (cmd.nil? ? "" : "/#{cmd}"), params, headers
93
+ end
94
+ end
@@ -0,0 +1,21 @@
1
+ module InfomemeClient::Functions::UserTransaction
2
+ def transactions(options = {})
3
+ return false unless authorized?
4
+ extract_or_response :transactions, :get, "/users/#{verified_user}/transactions", options
5
+ end
6
+
7
+ def transaction(transaction_id)
8
+ return false unless authorized?
9
+ extract_from_response :transaction, :get, "/users/#{verified_user}/transactions/#{transaction_id}"
10
+ end
11
+
12
+ def invoices(options = {})
13
+ transactions = transactions(options)
14
+ transactions.collect {|tr| tr.invoice} if transactions
15
+ end
16
+
17
+ def invoice(transaction_id)
18
+ transaction = transaction(transaction_id)
19
+ transaction.invoice if transaction
20
+ end
21
+ end
@@ -0,0 +1,16 @@
1
+ module InfomemeClient::Functions
2
+ autoload :Meme, "infomeme_client/functions/meme"
3
+ autoload :User, "infomeme_client/functions/user"
4
+ autoload :UserMeme, "infomeme_client/functions/user_meme"
5
+ autoload :UserTransaction, "infomeme_client/functions/user_transaction"
6
+
7
+ include Meme
8
+ include User
9
+ include UserMeme
10
+ include UserTransaction
11
+
12
+ private
13
+ def get_memes(path, options = {}, headers = {})
14
+ extract_or_response :memes, :get, path, options, headers
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ class InfomemeClient::MemeApplication
2
+ def initialize(options = {})
3
+ self.consumer = OAuth::Consumer.new(options[:api_key] || ::INFOMEME_API_KEY, options[:api_secret] || ::INFOMEME_API_SECRET, :site => options[:site] || ::INFOMEME_API_SITE)
4
+ self.token = OAuth::AccessToken.new(consumer)
5
+ end
6
+
7
+ def verify_access(meme_id, oauth_token, oauth_nonce, oauth_timestamp, oauth_signature)
8
+ handle_response :post, "/meme_app/verify_access", {:meme_id => meme_id, :verify_token => oauth_token, :verify_nonce => oauth_nonce, :verify_timestamp => oauth_timestamp, :verify_signature => oauth_signature}
9
+ end
10
+
11
+ def set_has_upload(meme_id, has_upload = true)
12
+ handle_response :put, "/meme_app/meme/#{meme_id}", {:has_upload => has_upload}
13
+ end
14
+
15
+ private
16
+ attr_accessor :consumer, :token
17
+ include InfomemeClient::Communication
18
+ end
@@ -0,0 +1,22 @@
1
+ module InfomemeClient::Permissions
2
+ def all_permissions
3
+ handle_response :get, "/oauth/permissions" do |resp|
4
+ resp.permissions unless resp.error?
5
+ end
6
+ end
7
+
8
+ def has_permission?(perm)
9
+ authorized? && permissions && permissions.include?(perm)
10
+ end
11
+
12
+ private
13
+ attr_accessor :permissions
14
+
15
+ def refresh_permissions
16
+ self.permissions = nil
17
+ return false unless authorized?
18
+ response = get "/users/#{verified_user}/permissions"
19
+ return false if response.error?
20
+ self.permissions = response.permissions
21
+ end
22
+ end
@@ -0,0 +1,51 @@
1
+ class InfomemeClient::Response < InfomemeClient::EntityHash
2
+ STATUS_FAILED = -1
3
+ STATUS_OK = 0
4
+ STATUS_ERROR = 1
5
+
6
+ ERRORS = {
7
+ "request_failed" => InfomemeClient::Error::RequestFailed,
8
+ "error" => InfomemeClient::Error,
9
+ "internal_error" => InfomemeClient::Error::InternalError,
10
+ "no_access" => InfomemeClient::Error::NoAccess,
11
+ "not_found" => InfomemeClient::Error::NotFound,
12
+ }.freeze
13
+
14
+ def initialize(response)
15
+ super(response.is_a?(Exception) ? {:status => STATUS_FAILED, :message => "Request failed.", :error_code => "request_failed", :errors => {:base => {response.class.name.to_sym => response.message}}} : response, true)
16
+ ERRORS.each do |key, val|
17
+ instance_eval "def #{val.name.split('::').last.sub(/\b\w/) { $&.downcase }}Error?; error_code == #{key}; end"
18
+ end
19
+ freeze
20
+ end
21
+
22
+ def failed?
23
+ status == STATUS_FAILED
24
+ end
25
+
26
+ def error?
27
+ status != STATUS_OK
28
+ end
29
+
30
+ def raise_error(options = {})
31
+ return false unless error?
32
+ return false if options.key?(:only) && ! options[:only].include?(error_code)
33
+ return false if options.key?(:except) && options[:except].include?(error_code)
34
+ err = ERRORS.key?(error_code) ? ERRORS[error_code] : InfomemeClient::Error
35
+ raise err, [(respond_to?(:errors) ? errors.to_hash : nil), message]
36
+ end
37
+
38
+ def extract(key, *extra_args)
39
+ return nil unless @hsh.key?(key)
40
+ klass = case key
41
+ when :comments then InfomemeClient::EntityHash::Comment
42
+ when :meme, :memes then InfomemeClient::EntityHash::Meme
43
+ when :meme_types then InfomemeClient::EntityHash::MemeType
44
+ when :user then InfomemeClient::EntityHash::User
45
+ when :transaction, :transactions then InfomemeClient::EntityHash::Transaction
46
+ else InfomemeClient::EntityHash
47
+ end
48
+ stored = to_hash[key]
49
+ stored.is_a?(Array) ? stored.collect {|val| klass.new *[val, extra_args]} : klass.new(*[stored, extra_args])
50
+ end
51
+ end
@@ -0,0 +1,21 @@
1
+ require "oauth"
2
+ require "json"
3
+ require "net/http/post/multipart"
4
+
5
+ class InfomemeClient
6
+ require "infomeme_client/errors"
7
+
8
+ autoload :EntityHash, "infomeme_client/entity_hash"
9
+ autoload :Response, "infomeme_client/response"
10
+ autoload :Base, "infomeme_client/base"
11
+ autoload :Communication, "infomeme_client/communication"
12
+ autoload :Permissions, "infomeme_client/permissions"
13
+ autoload :Functions, "infomeme_client/functions"
14
+
15
+ autoload :MemeApplication, "infomeme_client/meme_application"
16
+
17
+ include Base
18
+ include Communication
19
+ include Permissions
20
+ include Functions
21
+ end
@@ -0,0 +1 @@
1
+ {"status":0,"message":"Success.","comments":[{"comment":"test comment 1","user":{"username":"test_user"},"created_at":"2010-01-01 12:00:00"},{"comment":"test comment 2","user":{"username":"test_user"},"created_at":"2010-01-01 11:00:00"},{"comment":"test comment 3","user":{"username":"test_user"},"created_at":"2010-01-01 10:00:00"}],"pages":1,"count":3}
@@ -0,0 +1 @@
1
+ {"status":0,"message":"Success.","meme":{"id":1,"name":"test meme 1"}}
@@ -0,0 +1 @@
1
+ {"status":0,"message":"Success.","memes":[{"id":1,"name":"test meme 1"},{"id":2,"name":"test meme 2"},{"id":3,"name":"test meme 3"},{"id":4,"name":"test meme 4"}],"pages":1,"count":4}
@@ -0,0 +1 @@
1
+ {"status":0,"message":"Success.","meme_types":[{"id":1,"name":"TEST","url":"http://test.url","summary":"test summary","description":"test description"}]}
@@ -0,0 +1 @@
1
+ {"status":0,"message":"Success.","access_token":{"token":"test_token","secret":"test_secret"}}
@@ -0,0 +1 @@
1
+ {"status":0,"message":"Success.","verifier":"test_verifier"}
@@ -0,0 +1 @@
1
+ {"status":0,"message":"Success.","permissions":[{"id":0,"name":"memes","description":"Meme functionality (comment, rate, publish, etc.)."},{"id":1,"name":"private_data","description":"Access to private data (firstname, lastname, cleared and pending balance)."},{"id":2,"name":"order","description":"Order functionality (order, transactions, invoices, etc.)."}]}
@@ -0,0 +1 @@
1
+ {"status":0,"message":"Success.","request_token":{"token":"test_token","secret":"test_secret"}}
@@ -0,0 +1 @@
1
+ {"status":0,"message":"Success.","user_id":"test_user"}
@@ -0,0 +1 @@
1
+ {"status":1,"message":"Error.","error_code":"error","errors":{"test":{"test":"test error"}}}
@@ -0,0 +1 @@
1
+ {"status":0,"message":"Success."}
@@ -0,0 +1 @@
1
+ {"status":0,"message":"Success.","test_message":"test message"}
@@ -0,0 +1 @@
1
+ {"status":0,"message":"Success.","user":{"username":"test_user","email":"test@email.tld"}}
@@ -0,0 +1 @@
1
+ {"status":0,"message":"Success.","memes":[{"id":1,"name":"test meme 1"},{"id":2,"name":"test meme 2"},{"id":3,"name":"test meme 3"},{"id":4,"name":"test meme 4"}],"pages":1,"count":4}
@@ -0,0 +1 @@
1
+ {"status":0,"message":"Success.","permissions":[0,1,2]}
@@ -0,0 +1 @@
1
+ {"status":0,"message":"Success.","user":{"username":"test_user","comments":3,"ratings":3,"language":"en","confirmed":true,"can_publish":true,"language":"en"}}
@@ -0,0 +1 @@
1
+ {"status":0,"message":"Success.","user":{"username":"test_user","comments":3,"ratings":3}}
data/test/helper.rb ADDED
@@ -0,0 +1,69 @@
1
+ require "rubygems"
2
+ require "test/unit"
3
+ require "fakeweb"
4
+
5
+ FakeWeb.allow_net_connect = false
6
+
7
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
8
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
9
+ require "infomeme_client"
10
+
11
+ class Test::Unit::TestCase
12
+ def setup
13
+ @test_site = "https://test.api.site"
14
+ @test_api_key = "TEST_API_KEY"
15
+ @test_api_secret = "TEST_API_KEY"
16
+ @im_client = InfomemeClient.new :api_key => @test_api_key, :api_secret => @test_api_secret, :site => @test_site
17
+ end
18
+
19
+ private
20
+ def fake_request(method, url, options)
21
+ FakeWeb.register_uri(method, infomeme_url(url), options)
22
+ end
23
+
24
+ def fake_authorize_requests
25
+ fake_request(:get, "/oauth/verify_access", :body => fixture("oauth/verify_access"), :content_type => "application/json")
26
+ fake_request(:get, "/users/test_user", :body => fixture("users/user"), :content_type => "application/json")
27
+ fake_request(:get, "/users/test_user/permissions", :body => fixture("users/permissions"), :content_type => "application/json")
28
+ end
29
+
30
+ def authorize
31
+ fake_authorize_requests
32
+ assert_nothing_raised do
33
+ @im_client.authorize_with_token("test_token", "test_secret")
34
+ end
35
+ assert @im_client.authorized?
36
+ end
37
+
38
+ def fixture(filename)
39
+ File.read(File.dirname(__FILE__) + "/fixtures/#{filename}.json")
40
+ end
41
+
42
+ def infomeme_url(url)
43
+ url =~ /^http/ ? url : "#{@test_site}#{url}"
44
+ end
45
+
46
+ def check_paged(type, resp, options = {})
47
+ assert_instance_of InfomemeClient::Response, resp
48
+ assert_respond_to resp, type.to_sym
49
+ assert_respond_to resp, :pages
50
+ assert_respond_to resp, :count
51
+ check_list(type, resp.extract(type.to_sym))
52
+ assert_kind_of Integer, resp.pages
53
+ assert_kind_of Integer, resp.count
54
+ end
55
+
56
+ def check_list(type, list)
57
+ assert_instance_of Array, list
58
+ type = type.to_s.sub(/s\z/, "").to_sym
59
+ list.each do |elm|
60
+ check_eh(type, elm)
61
+ end
62
+ end
63
+
64
+ def check_eh(type, obj)
65
+ klass = InfomemeClient::EntityHash.const_get(type.to_s.split("_").map {|t| t.capitalize}.join.to_sym)
66
+ assert_instance_of Class, klass, "couldn't determine class from #{type.inspect} (#{klass.inspect})"
67
+ assert_instance_of klass, obj
68
+ end
69
+ end
@@ -0,0 +1,56 @@
1
+ require "helper"
2
+
3
+ class TestAuthorization < Test::Unit::TestCase
4
+ def test_request_authorization
5
+ fake_request(:get, "/oauth/request_token", :body => fixture("oauth/request_token"), :content_type => "application/json")
6
+ req_token = nil
7
+ assert_nothing_raised do
8
+ req_token = @im_client.request_authorization
9
+ end
10
+ assert_kind_of InfomemeClient::EntityHash, req_token
11
+ assert_respond_to req_token, :token, req_token.inspect
12
+ assert_respond_to req_token, :secret, req_token.inspect
13
+ assert_equal "test_token", req_token.token, req_token.inspect
14
+ assert_equal "test_secret", req_token.secret, req_token.inspect
15
+ end
16
+
17
+ def test_authorize_with_verifier
18
+ fake_request(:get, "/oauth/access_token?oauth_verifier=test_verifier", :body => fixture("oauth/access_token"), :content_type => "application/json")
19
+ fake_authorize_requests
20
+ assert_nothing_raised do
21
+ @im_client.authorize_with_verifier("test_token", "test_secret", "test_verifier")
22
+ end
23
+ check_authorized
24
+ end
25
+
26
+ def test_authorize_with_token
27
+ authorize
28
+ check_authorized
29
+ end
30
+
31
+ def test_authorize_with_credentials
32
+ fake_request(:get, "/oauth/request_token", :body => fixture("oauth/request_token"), :content_type => "application/json")
33
+ fake_request(:get, "/oauth/permissions", :body => fixture("oauth/permissions"), :content_type => "application/json")
34
+ fake_request(:put, "/oauth/authorize", :body => fixture("oauth/authorize"), :content_type => "application/json")
35
+ fake_request(:get, "/oauth/access_token?oauth_verifier=test_verifier", :body => fixture("oauth/access_token"), :content_type => "application/json")
36
+ fake_authorize_requests
37
+ assert_nothing_raised do
38
+ @im_client.authorize_with_credentials("test_login", "test_password")
39
+ end
40
+ check_authorized
41
+ assert @im_client.has_permission?(0)
42
+ assert @im_client.has_permission?(1)
43
+ assert @im_client.has_permission?(2)
44
+ end
45
+
46
+ private
47
+ def check_authorized
48
+ assert @im_client.authorized?
49
+ assert @im_client.confirmed?
50
+ assert @im_client.can_publish?
51
+ cred = @im_client.credentials
52
+ assert_equal "test_user", cred[:login]
53
+ assert_equal "test_token", cred[:token]
54
+ assert_equal "test_secret", cred[:secret]
55
+ end
56
+ end