ruby-rapleafbg 0.2.3f
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +45 -0
- data/Manifest.txt +10 -0
- data/README.txt +140 -0
- data/Rakefile +28 -0
- data/examples/person.rb +65 -0
- data/lib/rapleaf/exceptions.rb +61 -0
- data/lib/rapleaf/rapleaf.rb +153 -0
- data/lib/rapleaf/responses.rb +142 -0
- data/lib/ruby-rapleaf.rb +26 -0
- data/ruby-rapleaf.gemspec +38 -0
- metadata +132 -0
data/History.txt
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
=== 0.2.3 / 2010/11/17
|
2
|
+
|
3
|
+
* Updated for v4 methods.
|
4
|
+
|
5
|
+
=== 0.2.2 / 2010/10/18
|
6
|
+
|
7
|
+
* Allow specifying the read_timeout to pass through to Net::HTTP.
|
8
|
+
There are a few reasons why you might want to do this. One is that
|
9
|
+
Net::HTTP's read_timeout is implemented using timeout.rb, which is known
|
10
|
+
to have race conditions, and in particular is unsafe to use in
|
11
|
+
EventMachine (because it can sometimes throw exceptions in the main
|
12
|
+
event loop and kill the whole process); so this lets you disable the
|
13
|
+
timeout entirely.
|
14
|
+
|
15
|
+
* Ruby 1.9 compatibility tweak (thanks to Justin Ip)
|
16
|
+
|
17
|
+
=== 0.2.1 / 2010/04/27
|
18
|
+
|
19
|
+
* If unexpected response code, exception should include diagnostic info
|
20
|
+
|
21
|
+
=== 0.2.0 / 2010/04/24
|
22
|
+
|
23
|
+
* Support Person API lookup by site profile (e.g. Twitter username) for API v3.
|
24
|
+
|
25
|
+
=== 0.1.7 / 2010-04-14
|
26
|
+
|
27
|
+
* URLencode email addresses before sending them to Rapleaf.
|
28
|
+
|
29
|
+
* Remove workaround for mistakenly diagnosed problem (thought Rapleaf rejected emails containing '+', they just required encoding).
|
30
|
+
|
31
|
+
* Use existing PersonEmailHashNotFound exception for 404 when looking up by hash
|
32
|
+
|
33
|
+
* removed NotFound class added in 0.1.6
|
34
|
+
|
35
|
+
=== 0.1.6 / 2010-03-04
|
36
|
+
|
37
|
+
* Modified by Sam Stokes
|
38
|
+
|
39
|
+
* Support for Rapleaf Person API v3 (which is now the default)
|
40
|
+
|
41
|
+
* Work around Rapleaf bug: they think email addresses containing '+' are malformed, so for those we send them hashes instead.
|
42
|
+
|
43
|
+
=== 0.1.5 / 2008-08-28
|
44
|
+
|
45
|
+
* Original version by Glenn Rempe, with support for Rapleaf Person API v2
|
data/Manifest.txt
ADDED
data/README.txt
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
= ruby-rapleaf
|
2
|
+
|
3
|
+
* http://github.com/rapportive-oss/ruby-rapleaf
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
Rapleaf's goal is to make the internet safe and transparent, by allowing you
|
8
|
+
to evaluate your web footprint across a variety of user-generated sites.
|
9
|
+
See http://www.rapleaf.com for more information.
|
10
|
+
|
11
|
+
== FEATURES/PROBLEMS:
|
12
|
+
|
13
|
+
This library was inspired by the sample code provided by Rapleaf at:
|
14
|
+
|
15
|
+
http://trac.rapleaf.com/ruby-api-kit/wiki
|
16
|
+
|
17
|
+
The code was extensively re-written by Glenn Rempe so it would work with the
|
18
|
+
then-current Rapleaf v2 API, and further modified by Sam Stokes to support the
|
19
|
+
v3 API.
|
20
|
+
|
21
|
+
Please direct any questions, patches, pull requests or bug reports to
|
22
|
+
Sam Stokes <sam@rapportive.com>.
|
23
|
+
|
24
|
+
This project is not affiliated with, or endorsed or supported by, Rapleaf.
|
25
|
+
|
26
|
+
=== Original (v2 API compatible)
|
27
|
+
|
28
|
+
http://github.com/grempe/ruby-rapleaf
|
29
|
+
|
30
|
+
Glenn Rempe
|
31
|
+
glenn@rempe.us
|
32
|
+
|
33
|
+
=== Updated (v3 API compatible)
|
34
|
+
|
35
|
+
http://github.com/rapportive-oss/ruby-rapleaf
|
36
|
+
|
37
|
+
Sam Stokes
|
38
|
+
sam@rapportive.com
|
39
|
+
|
40
|
+
== SYNOPSIS:
|
41
|
+
|
42
|
+
In order to use this API, you will need to get an API Key from Rapleaf. These
|
43
|
+
can be obtained free at http://www.rapleaf.com/.
|
44
|
+
|
45
|
+
To run the samples you will need to put your API Key in the
|
46
|
+
examples/person.rb file or the examples will fail.
|
47
|
+
|
48
|
+
To run any of the examples, simply run it like:
|
49
|
+
|
50
|
+
cd examples
|
51
|
+
ruby person.rb
|
52
|
+
|
53
|
+
(There are some known problems running the examples at the moment... sorry!)
|
54
|
+
|
55
|
+
== REQUIREMENTS:
|
56
|
+
|
57
|
+
The following gems are required for installation of the ruby-rapleaf gem.
|
58
|
+
|
59
|
+
* xml-simple
|
60
|
+
* builder
|
61
|
+
|
62
|
+
== INSTALL:
|
63
|
+
|
64
|
+
gem install ruby-rapleaf
|
65
|
+
|
66
|
+
You can build the gem yourself and install as a Ruby Gem with:
|
67
|
+
|
68
|
+
git clone git://github.com/rapportive-oss/ruby-rapleaf.git
|
69
|
+
cd ruby-rapleaf
|
70
|
+
gem build ruby-rapleaf.gemspec
|
71
|
+
gem install ruby-rapleaf-*.gem
|
72
|
+
|
73
|
+
== LICENSE:
|
74
|
+
|
75
|
+
This software is distributed under the Ruby License. A copy of which is
|
76
|
+
provided below.
|
77
|
+
|
78
|
+
RUBY LICENSE
|
79
|
+
|
80
|
+
Copyright (c) 2008-2010 Glenn Rempe, 2010 Sam Stokes, Justin Ip
|
81
|
+
|
82
|
+
http://www.ruby-lang.org/en/LICENSE.txt
|
83
|
+
|
84
|
+
Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.co.jp>.
|
85
|
+
You can redistribute it and/or modify it under either the terms of the GPL
|
86
|
+
(see COPYING.txt file), or the conditions below:
|
87
|
+
|
88
|
+
1. You may make and give away verbatim copies of the source form of the
|
89
|
+
software without restriction, provided that you duplicate all of the
|
90
|
+
original copyright notices and associated disclaimers.
|
91
|
+
|
92
|
+
2. You may modify your copy of the software in any way, provided that
|
93
|
+
you do at least ONE of the following:
|
94
|
+
|
95
|
+
a) place your modifications in the Public Domain or otherwise
|
96
|
+
make them Freely Available, such as by posting said
|
97
|
+
modifications to Usenet or an equivalent medium, or by allowing
|
98
|
+
the author to include your modifications in the software.
|
99
|
+
|
100
|
+
b) use the modified software only within your corporation or
|
101
|
+
organization.
|
102
|
+
|
103
|
+
c) rename any non-standard executables so the names do not conflict
|
104
|
+
with standard executables, which must also be provided.
|
105
|
+
|
106
|
+
d) make other distribution arrangements with the author.
|
107
|
+
|
108
|
+
3. You may distribute the software in object code or executable
|
109
|
+
form, provided that you do at least ONE of the following:
|
110
|
+
|
111
|
+
a) distribute the executables and library files of the software,
|
112
|
+
together with instructions (in the manual page or equivalent)
|
113
|
+
on where to get the original distribution.
|
114
|
+
|
115
|
+
b) accompany the distribution with the machine-readable source of
|
116
|
+
the software.
|
117
|
+
|
118
|
+
c) give non-standard executables non-standard names, with
|
119
|
+
instructions on where to get the original software distribution.
|
120
|
+
|
121
|
+
d) make other distribution arrangements with the author.
|
122
|
+
|
123
|
+
4. You may modify and include the part of the software into any other
|
124
|
+
software (possibly commercial). But some files in the distribution
|
125
|
+
are not written by the author, so that they are not under this terms.
|
126
|
+
|
127
|
+
They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some
|
128
|
+
files under the ./missing directory. See each file for the copying
|
129
|
+
condition.
|
130
|
+
|
131
|
+
5. The scripts and library files supplied as input to or produced as
|
132
|
+
output from the software do not automatically fall under the
|
133
|
+
copyright of the software, but belong to whomever generated them,
|
134
|
+
and may be sold commercially, and may be aggregated with this
|
135
|
+
software.
|
136
|
+
|
137
|
+
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
138
|
+
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
139
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
140
|
+
PURPOSE.
|
data/Rakefile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
require './lib/ruby-rapleaf.rb'
|
6
|
+
|
7
|
+
Hoe.new('ruby-rapleaf', Rapleaf::VERSION) do |p|
|
8
|
+
p.rubyforge_name = 'ruby-rapleaf' # if different than lowercase project name
|
9
|
+
p.developer('Glenn Rempe', 'glenn@rempe.us')
|
10
|
+
p.extra_deps = [['xml-simple', '>= 1.0.11'], ['builder', '>= 2.1.2']]
|
11
|
+
end
|
12
|
+
|
13
|
+
namespace :manifest do
|
14
|
+
desc 'Recreate Manifest.txt to include ALL files'
|
15
|
+
task :refresh do
|
16
|
+
`rake check_manifest | patch -p0 > Manifest.txt`
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
namespace :gemspec do
|
21
|
+
desc 'Refresh the gemspec file'
|
22
|
+
task :refresh do
|
23
|
+
`rake debug_gem > ruby-rapleaf.gemspec`
|
24
|
+
# remove the first line from the file which is an artifact of the gemspec generation
|
25
|
+
`perl -pi -e '$_ = "" if ($. == 1);' ruby-rapleaf.gemspec`
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
data/examples/person.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/ruby-rapleaf'
|
3
|
+
|
4
|
+
# Instanciate a Rapleaf object with your API Key.
|
5
|
+
@rapleaf = Rapleaf::Base.new('REPLACE_WITH_YOUR_API_KEY')
|
6
|
+
|
7
|
+
@person = @rapleaf.person(:email => 'dummy@rapleaf.com')
|
8
|
+
|
9
|
+
puts "\n\n"
|
10
|
+
puts "BASICS"
|
11
|
+
|
12
|
+
puts "\n@person.basics.name:"
|
13
|
+
puts @person.basics.name
|
14
|
+
|
15
|
+
puts "\n@person.basics.age:"
|
16
|
+
puts @person.basics.age
|
17
|
+
|
18
|
+
puts "\n@person.basics.gender:"
|
19
|
+
puts @person.basics.gender
|
20
|
+
|
21
|
+
puts "\n@person.basics.location:"
|
22
|
+
puts @person.basics.location
|
23
|
+
|
24
|
+
puts "\n@person.basics.occupations:"
|
25
|
+
if @person.basics.occupations
|
26
|
+
@person.basics.occupations.each do |occupation|
|
27
|
+
puts "occupation.job_title"
|
28
|
+
puts occupation.job_title
|
29
|
+
puts "occupation.company"
|
30
|
+
puts occupation.company
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
puts "\n@person.basics.universities:"
|
35
|
+
if @person.basics.universities
|
36
|
+
@person.basics.universities.each do |university|
|
37
|
+
puts "university:"
|
38
|
+
puts university
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
puts "\n@person.basics.earliest_known_activity:"
|
43
|
+
puts @person.basics.earliest_known_activity
|
44
|
+
|
45
|
+
puts "\n@person.basics.latest_known_activity:"
|
46
|
+
puts @person.basics.latest_known_activity
|
47
|
+
|
48
|
+
puts "\n@person.basics.num_friends:"
|
49
|
+
puts @person.basics.num_friends
|
50
|
+
|
51
|
+
puts "\nMEMBERSHIPS"
|
52
|
+
|
53
|
+
puts "\n@person.memberships.inspect"
|
54
|
+
puts @person.memberships.inspect
|
55
|
+
|
56
|
+
puts "\n@person.memberships.primary.inspect"
|
57
|
+
puts @person.memberships.primary.inspect
|
58
|
+
|
59
|
+
puts "\n@person.memberships.primary.membership[0].site"
|
60
|
+
puts @person.memberships.primary.membership[0].site
|
61
|
+
|
62
|
+
# Look up a profile by hashed email address.
|
63
|
+
puts "\nLookup by hashed email:"
|
64
|
+
@person = @rapleaf.person(:email => '1147e414eec8b785fb760f13f7890a767ffaef6e')
|
65
|
+
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Rapleaf
|
2
|
+
|
3
|
+
# CLIENT SIDE ERRORS
|
4
|
+
|
5
|
+
# All of our errors are superclassed by Error < RuntimeError
|
6
|
+
class Error < RuntimeError #:nodoc:
|
7
|
+
end
|
8
|
+
|
9
|
+
# A client side only argument error
|
10
|
+
class ArgumentError < Error #:nodoc:
|
11
|
+
end
|
12
|
+
|
13
|
+
# SERVER SIDE ERRORS
|
14
|
+
|
15
|
+
# GENERAL API
|
16
|
+
# =============================================
|
17
|
+
|
18
|
+
# 401 Unauthorized
|
19
|
+
# API key was not provided or is invalid.
|
20
|
+
class AuthFailure < Error #:nodoc:
|
21
|
+
end
|
22
|
+
|
23
|
+
# 403 Forbidden
|
24
|
+
# Your query limit has been exceeded.
|
25
|
+
class ForbiddenQueryLimitExceeded < Error #:nodoc:
|
26
|
+
end
|
27
|
+
|
28
|
+
# 500 Internal Server Error
|
29
|
+
# There was an unexpected error on our server. This should be very
|
30
|
+
# rare and if you see it please contact developer@rapleaf.com.
|
31
|
+
class InternalServerError < Error #:nodoc:
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
# PERSON API
|
36
|
+
# =============================================
|
37
|
+
|
38
|
+
# 202 Accepted
|
39
|
+
# This person is currently being searched. Check back shortly and we should have data.
|
40
|
+
class PersonAccepted < Error #:nodoc:
|
41
|
+
end
|
42
|
+
|
43
|
+
# 400 Bad Request
|
44
|
+
# Invalid email address.
|
45
|
+
class PersonBadRequestInvalidEmail < Error #:nodoc:
|
46
|
+
end
|
47
|
+
|
48
|
+
# 404 Not Found
|
49
|
+
# Only returned for lookup by hash. We do not have this email in our
|
50
|
+
# system and are not able to create a person using a hash. If you would
|
51
|
+
# like better results, consider supplying the unhashed email address.
|
52
|
+
class PersonEmailHashNotFound < Error #:nodoc:
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
# ABOOK API
|
57
|
+
# =============================================
|
58
|
+
|
59
|
+
# TODO
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
module Rapleaf
|
5
|
+
class Base
|
6
|
+
|
7
|
+
def initialize(api_key, options = {})
|
8
|
+
#personalize.rlcdn.com
|
9
|
+
options = {
|
10
|
+
:api_host => API_HOST,
|
11
|
+
:api_host_v4 => API_HOST_V4,
|
12
|
+
:api_port => API_PORT,
|
13
|
+
:api_version => API_VERSION,
|
14
|
+
:api_read_timeout => 30,
|
15
|
+
}.merge(options)
|
16
|
+
|
17
|
+
@api_key = api_key
|
18
|
+
@host = options[:api_host]
|
19
|
+
@host_v4 = options[:api_host_v4]
|
20
|
+
@port = options[:api_port]
|
21
|
+
@version = options[:api_version]
|
22
|
+
@read_timeout = options[:api_read_timeout]
|
23
|
+
end
|
24
|
+
|
25
|
+
# This resource is used to retrieve information about a person, identified
|
26
|
+
# using an email address or email address hash.
|
27
|
+
# Examples:
|
28
|
+
# person(:email => 'dummy@rapleaf.com')
|
29
|
+
# person(:site => :twitter, :profile => 'samstokes')
|
30
|
+
# person(:sha1 => Digest::SHA1.hexdigest('dummy@rapleaf.com'))
|
31
|
+
# person(:md5 => Digest::MD5.hexdigest('dummy@rapleaf.com'))
|
32
|
+
def person( opts = {} )
|
33
|
+
resp = fetch_response(URI.parse(person_url(opts)))
|
34
|
+
|
35
|
+
case resp.code
|
36
|
+
when '200'
|
37
|
+
#return Response.parse(:xml => resp.body)
|
38
|
+
return ActiveSupport::JSON.decode(resp.body)
|
39
|
+
when '202'
|
40
|
+
raise PersonAccepted, 'This person is currently being searched. Check back shortly and we should have data.'
|
41
|
+
when '400'
|
42
|
+
raise PersonBadRequestInvalidEmail, 'Invalid email address.'
|
43
|
+
when '401'
|
44
|
+
raise AuthFailure, 'API key was not provided or is invalid.'
|
45
|
+
when '403'
|
46
|
+
raise ForbiddenQueryLimitExceeded, 'Your query limit has been exceeded. Contact developer@rapleaf.com if you would like to increase your limit.'
|
47
|
+
when '404'
|
48
|
+
raise PersonEmailHashNotFound, 'We do not have this email in our system and are not able to create a person using a hash. If you would like better results, consider supplying the unhashed email address.'
|
49
|
+
when '500'
|
50
|
+
raise InternalServerError, 'There was an unexpected error on our server. This should be very rare and if you see it please contact developer@rapleaf.com.'
|
51
|
+
else
|
52
|
+
msg = resp.body[0,50]
|
53
|
+
msg << "..." if 50 < resp.body.length
|
54
|
+
raise Error, %(Unexpected response code #{resp.code}: "#{msg}")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
def fetch_response(uri)
|
60
|
+
# Have to do this a verbose way in order to override Net::HTTP's
|
61
|
+
# default read_timeout
|
62
|
+
|
63
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
64
|
+
if uri.scheme == 'https'
|
65
|
+
http.use_ssl = true
|
66
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
67
|
+
end
|
68
|
+
http.read_timeout = @read_timeout
|
69
|
+
|
70
|
+
http.start { http.get(uri.path + '?' + uri.query) }
|
71
|
+
end
|
72
|
+
|
73
|
+
def person_url(opts)
|
74
|
+
email = opts[:email]
|
75
|
+
|
76
|
+
site_profile = [opts[:site], opts[:profile]]
|
77
|
+
if site_profile.any?
|
78
|
+
raise ArgumentError, 'Require both :site and :profile if either is specified' unless site_profile.all?
|
79
|
+
else
|
80
|
+
site_profile = nil
|
81
|
+
end
|
82
|
+
|
83
|
+
md5 = opts[:md5]
|
84
|
+
sha1 = opts[:sha1]
|
85
|
+
|
86
|
+
# Rapleaf requires email addresses be urlencoded
|
87
|
+
# Pass our own "unsafe regex" as URI.escape's default is too permissive
|
88
|
+
# (lets + through, but Rapleaf rejects it)
|
89
|
+
email = URI.escape(email, /[^a-zA-Z0-9.\-_]/) if email
|
90
|
+
|
91
|
+
selector = [email, site_profile, md5, sha1].compact
|
92
|
+
raise ArgumentError, 'Please provide only one of :email, [:site and :profile], :md5 or :sha1' if selector.size > 1
|
93
|
+
raise ArgumentError, 'Person selector must be provided' if selector.empty? || '' == selector[0]
|
94
|
+
|
95
|
+
case @version
|
96
|
+
when "v2"
|
97
|
+
if site_profile
|
98
|
+
raise ArgumentError, 'Query by website ID requires API v3 or greater'
|
99
|
+
end
|
100
|
+
person_url_v2_by_email_or_hash(email_or_hash[0])
|
101
|
+
when "v3"
|
102
|
+
if email
|
103
|
+
person_url_v3_by_email(email)
|
104
|
+
elsif site_profile
|
105
|
+
person_url_v3_by_site_profile(*site_profile)
|
106
|
+
elsif md5
|
107
|
+
person_url_v3_by_hash(:md5, md5)
|
108
|
+
else
|
109
|
+
person_url_v3_by_hash(:sha1, sha1)
|
110
|
+
end
|
111
|
+
when "v4"
|
112
|
+
if email
|
113
|
+
person_url_v4_by_email(email)
|
114
|
+
elsif site_profile
|
115
|
+
person_url_v4_by_site_profile(*site_profile)
|
116
|
+
elsif md5
|
117
|
+
person_url_v4_by_hash(:md5, md5)
|
118
|
+
else
|
119
|
+
person_url_v4_by_hash(:sha1, sha1)
|
120
|
+
end
|
121
|
+
else
|
122
|
+
raise ArgumentError, "Person queries not supported for API version #{@version}"
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def person_url_v2_by_email_or_hash(email_or_hash)
|
127
|
+
"http://#{@host}:#{@port}/v2/person/#{email_or_hash}?api_key=#{@api_key}"
|
128
|
+
end
|
129
|
+
|
130
|
+
def person_url_v3_by_email(email)
|
131
|
+
"http://#{@host}:#{@port}/v3/person/email/#{email}?api_key=#{@api_key}"
|
132
|
+
end
|
133
|
+
|
134
|
+
def person_url_v4_by_email(email)
|
135
|
+
"https://#{@host_v4}/v4/dr?email=#{email}&api_key=#{@api_key}"
|
136
|
+
end
|
137
|
+
|
138
|
+
def person_url_v3_by_site_profile(site, profile)
|
139
|
+
# TODO validate param formats
|
140
|
+
"http://#{@host}:#{@port}/v3/person/web/#{site}/#{profile}?api_key=#{@api_key}"
|
141
|
+
end
|
142
|
+
|
143
|
+
def person_url_v3_by_hash(algo, hash)
|
144
|
+
"http://#{@host}:#{@port}/v3/person/hash/#{algo}/#{hash}?api_key=#{@api_key}"
|
145
|
+
end
|
146
|
+
|
147
|
+
def person_url_v4_by_hash(algo, hash)
|
148
|
+
"https://#{@host_v4}/v4/dr?#{algo}=#{hash}&api_key=#{@api_key}"
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
module Rapleaf
|
2
|
+
|
3
|
+
# Credits :
|
4
|
+
# I learned the magic of making an OpenStruct object able to respond as a fully Enumerable
|
5
|
+
# object (responds to .each, etc.) thanks to a great blog article on Struct and OpenStruct
|
6
|
+
# at http://errtheblog.com/post/30
|
7
|
+
#
|
8
|
+
# Thanks to Sean Knapp for the XmlSimple response patch which greatly simplified the response
|
9
|
+
# mechanism for the whole library while making it more accurate and much less brittle to boot!
|
10
|
+
#
|
11
|
+
|
12
|
+
require 'rubygems'
|
13
|
+
begin
|
14
|
+
require 'xmlsimple' unless defined? XmlSimple
|
15
|
+
rescue Exception => e
|
16
|
+
require 'xml-simple' unless defined? XmlSimple
|
17
|
+
end
|
18
|
+
|
19
|
+
class Response < OpenStruct
|
20
|
+
|
21
|
+
include Enumerable
|
22
|
+
|
23
|
+
def self.parse(options = {})
|
24
|
+
options = {
|
25
|
+
:xml => "",
|
26
|
+
:parse_options => { 'ForceArray' => ['item'], 'SuppressEmpty' => nil }
|
27
|
+
}.merge(options)
|
28
|
+
response = Response.new(XmlSimple.xml_in(options[:xml], options[:parse_options]))
|
29
|
+
|
30
|
+
# set the xml attribute of the response object to contain the original XML that was
|
31
|
+
# returned. This allows anyone to bypass our parsing if desired and just
|
32
|
+
# get right at the raw XML response.
|
33
|
+
response.xml = options[:xml]
|
34
|
+
return response
|
35
|
+
end
|
36
|
+
|
37
|
+
# Every member of an OpenStruct object has getters and setters, the latter of which
|
38
|
+
# has a method ending in "=". Find all of these methods, excluding those defined on
|
39
|
+
# parent classes.
|
40
|
+
def members
|
41
|
+
methods(false).sort.grep(/=/).map { |m| m[0...-1] }
|
42
|
+
end
|
43
|
+
|
44
|
+
# Required by the Enumerable module. Iterate over each item in the members array
|
45
|
+
# and pass as a value the block passed to each using yield.
|
46
|
+
def each
|
47
|
+
members.each do |method|
|
48
|
+
yield send(method)
|
49
|
+
end
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
# Same as the each method, but with both key and value.
|
54
|
+
#
|
55
|
+
#Sample Use:
|
56
|
+
# obj.each_pair { |k,v| puts "key: #{k}, value: #{v}" }
|
57
|
+
def each_pair
|
58
|
+
members.each do |method|
|
59
|
+
yield method, send(method)
|
60
|
+
end
|
61
|
+
self
|
62
|
+
end
|
63
|
+
|
64
|
+
# Alternative method for getting members.
|
65
|
+
def [](member)
|
66
|
+
send(member)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Alternative method for setting members.
|
70
|
+
def []=(member, value)
|
71
|
+
send("#{member}=", value)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Helper for converting to string which support a long and short version
|
75
|
+
# to avoid recursion problems with parents.
|
76
|
+
def to_string(short=false)
|
77
|
+
s = "#<#{self.class}:0x#{(2 ** 32 + object_id).to_s(16).upcase}"
|
78
|
+
if (short)
|
79
|
+
s += " ..."
|
80
|
+
else
|
81
|
+
each_pair { |k,v|
|
82
|
+
if (v == self.parent && v.kind_of?(Response))
|
83
|
+
v = v.to_string(true)
|
84
|
+
elsif (v.kind_of?(String))
|
85
|
+
v = "\"#{v.gsub("\"", "\\\"")}\""
|
86
|
+
elsif (v.kind_of?(NilClass))
|
87
|
+
v = "nil"
|
88
|
+
end
|
89
|
+
s += " #{k}=#{v}"
|
90
|
+
}
|
91
|
+
end
|
92
|
+
s += ">"
|
93
|
+
return s
|
94
|
+
end
|
95
|
+
|
96
|
+
# Override of to string method.
|
97
|
+
def to_s
|
98
|
+
return to_string
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
# Initialize the object by passing data to the OpenStruct initialize method
|
104
|
+
# and then converting ourself to guarantee we have top-to-bottom data
|
105
|
+
# representation as a Response object.
|
106
|
+
def initialize(data, parent=nil)
|
107
|
+
super(data)
|
108
|
+
self.parent = parent
|
109
|
+
Response.convert(self, parent)
|
110
|
+
end
|
111
|
+
|
112
|
+
# The "brains" of our Response class. This method takes an arbitray object and
|
113
|
+
# depending on its class attempts to convert it.
|
114
|
+
def self.convert(obj, parent)
|
115
|
+
if (obj.kind_of?(Response))
|
116
|
+
# Recursively convert the object.
|
117
|
+
obj.each_pair { |k,v|
|
118
|
+
if (v != obj.parent)
|
119
|
+
obj[k] = convert(v, obj)
|
120
|
+
end
|
121
|
+
}
|
122
|
+
return obj
|
123
|
+
elsif (obj.kind_of?(Hash))
|
124
|
+
# Hashes make good Responses already thanks to OpenStruct.
|
125
|
+
return Response.new(obj, parent)
|
126
|
+
elsif (obj.kind_of?(Array))
|
127
|
+
# With arrays, make sure each element is appropriately converted.
|
128
|
+
new_arr = []
|
129
|
+
obj.each { |elem|
|
130
|
+
new_arr << convert(elem, parent)
|
131
|
+
}
|
132
|
+
return new_arr
|
133
|
+
else
|
134
|
+
# At this point we're out of ideas, so let's hope it is a string.
|
135
|
+
return obj
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
end # class Response < OpenStruct
|
140
|
+
|
141
|
+
end # module
|
142
|
+
|
data/lib/ruby-rapleaf.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'cgi'
|
3
|
+
require 'openssl'
|
4
|
+
require 'digest/sha1'
|
5
|
+
require 'net/http'
|
6
|
+
#require 'net/https'
|
7
|
+
require 'builder'
|
8
|
+
require 'ostruct'
|
9
|
+
|
10
|
+
library_files = Dir[File.join(File.dirname(__FILE__), "/rapleaf/**/*.rb")]
|
11
|
+
library_files.each do |file|
|
12
|
+
require file.gsub(/\.rb$/, "")
|
13
|
+
end
|
14
|
+
|
15
|
+
module Rapleaf
|
16
|
+
|
17
|
+
VERSION = '0.2.3e'
|
18
|
+
|
19
|
+
# API Constants
|
20
|
+
API_HOST = 'api.rapleaf.com'
|
21
|
+
API_HOST_V4 = 'personalize.rlcdn.com'
|
22
|
+
API_PORT = 80
|
23
|
+
API_VERSION = 'v4'
|
24
|
+
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = %q{ruby-rapleafbg}
|
3
|
+
s.version = "0.2.3f"
|
4
|
+
|
5
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
6
|
+
s.authors = ["Glenn Rempe", "Sam Stokes", "Justin Ip", "Brad Gilreath"]
|
7
|
+
s.date = %q{2010-11-17}
|
8
|
+
s.description = %q{Rapleaf's goal is to make the internet safe and transparent, by allowing you to evaluate your web footprint across a variety of user-generated sites. See http://www.rapleaf.com for more information. Cheap update for API v4.}
|
9
|
+
s.email = ["glenn@rempe.us", "sam@rapportive.com", "bwgilreath@gmail.com"]
|
10
|
+
s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"]
|
11
|
+
s.files = ["History.txt", "Manifest.txt", "README.txt", "Rakefile", "examples/person.rb", "lib/ruby-rapleaf.rb", "lib/rapleaf/exceptions.rb", "lib/rapleaf/rapleaf.rb", "lib/rapleaf/responses.rb", "ruby-rapleaf.gemspec"]
|
12
|
+
s.has_rdoc = true
|
13
|
+
s.homepage = %q{http://github.com/rapportive-oss/ruby-rapleaf}
|
14
|
+
s.rdoc_options = ["--main", "README.txt"]
|
15
|
+
s.require_paths = ["lib"]
|
16
|
+
s.rubyforge_project = %q{ruby-rapleaf}
|
17
|
+
s.rubygems_version = %q{1.2.0}
|
18
|
+
s.summary = %q{Rapleaf's goal is to make the internet safe and transparent, by allowing you to evaluate your web footprint across a variety of user-generated sites}
|
19
|
+
|
20
|
+
if s.respond_to? :specification_version then
|
21
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
22
|
+
s.specification_version = 2
|
23
|
+
|
24
|
+
if current_version >= 3 then
|
25
|
+
s.add_runtime_dependency(%q<xml-simple>, [">= 1.0.11"])
|
26
|
+
s.add_runtime_dependency(%q<builder>, [">= 2.1.2"])
|
27
|
+
s.add_development_dependency(%q<hoe>, [">= 1.7.0"])
|
28
|
+
else
|
29
|
+
s.add_dependency(%q<xml-simple>, [">= 1.0.11"])
|
30
|
+
s.add_dependency(%q<builder>, [">= 2.1.2"])
|
31
|
+
s.add_dependency(%q<hoe>, [">= 1.7.0"])
|
32
|
+
end
|
33
|
+
else
|
34
|
+
s.add_dependency(%q<xml-simple>, [">= 1.0.11"])
|
35
|
+
s.add_dependency(%q<builder>, [">= 2.1.2"])
|
36
|
+
s.add_dependency(%q<hoe>, [">= 1.7.0"])
|
37
|
+
end
|
38
|
+
end
|
metadata
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby-rapleafbg
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 3450188
|
5
|
+
prerelease: true
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
- 3f
|
10
|
+
version: 0.2.3f
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Glenn Rempe
|
14
|
+
- Sam Stokes
|
15
|
+
- Justin Ip
|
16
|
+
- Brad Gilreath
|
17
|
+
autorequire:
|
18
|
+
bindir: bin
|
19
|
+
cert_chain: []
|
20
|
+
|
21
|
+
date: 2010-11-17 00:00:00 -05:00
|
22
|
+
default_executable:
|
23
|
+
dependencies:
|
24
|
+
- !ruby/object:Gem::Dependency
|
25
|
+
name: xml-simple
|
26
|
+
prerelease: false
|
27
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
hash: 1
|
33
|
+
segments:
|
34
|
+
- 1
|
35
|
+
- 0
|
36
|
+
- 11
|
37
|
+
version: 1.0.11
|
38
|
+
type: :runtime
|
39
|
+
version_requirements: *id001
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: builder
|
42
|
+
prerelease: false
|
43
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
44
|
+
none: false
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
hash: 15
|
49
|
+
segments:
|
50
|
+
- 2
|
51
|
+
- 1
|
52
|
+
- 2
|
53
|
+
version: 2.1.2
|
54
|
+
type: :runtime
|
55
|
+
version_requirements: *id002
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: hoe
|
58
|
+
prerelease: false
|
59
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
hash: 11
|
65
|
+
segments:
|
66
|
+
- 1
|
67
|
+
- 7
|
68
|
+
- 0
|
69
|
+
version: 1.7.0
|
70
|
+
type: :development
|
71
|
+
version_requirements: *id003
|
72
|
+
description: Rapleaf's goal is to make the internet safe and transparent, by allowing you to evaluate your web footprint across a variety of user-generated sites. See http://www.rapleaf.com for more information. Cheap update for API v4.
|
73
|
+
email:
|
74
|
+
- glenn@rempe.us
|
75
|
+
- sam@rapportive.com
|
76
|
+
- bwgilreath@gmail.com
|
77
|
+
executables: []
|
78
|
+
|
79
|
+
extensions: []
|
80
|
+
|
81
|
+
extra_rdoc_files:
|
82
|
+
- History.txt
|
83
|
+
- Manifest.txt
|
84
|
+
- README.txt
|
85
|
+
files:
|
86
|
+
- History.txt
|
87
|
+
- Manifest.txt
|
88
|
+
- README.txt
|
89
|
+
- Rakefile
|
90
|
+
- examples/person.rb
|
91
|
+
- lib/ruby-rapleaf.rb
|
92
|
+
- lib/rapleaf/exceptions.rb
|
93
|
+
- lib/rapleaf/rapleaf.rb
|
94
|
+
- lib/rapleaf/responses.rb
|
95
|
+
- ruby-rapleaf.gemspec
|
96
|
+
has_rdoc: true
|
97
|
+
homepage: http://github.com/rapportive-oss/ruby-rapleaf
|
98
|
+
licenses: []
|
99
|
+
|
100
|
+
post_install_message:
|
101
|
+
rdoc_options:
|
102
|
+
- --main
|
103
|
+
- README.txt
|
104
|
+
require_paths:
|
105
|
+
- lib
|
106
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
hash: 3
|
112
|
+
segments:
|
113
|
+
- 0
|
114
|
+
version: "0"
|
115
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
|
+
none: false
|
117
|
+
requirements:
|
118
|
+
- - ">="
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
hash: 3
|
121
|
+
segments:
|
122
|
+
- 0
|
123
|
+
version: "0"
|
124
|
+
requirements: []
|
125
|
+
|
126
|
+
rubyforge_project: ruby-rapleaf
|
127
|
+
rubygems_version: 1.3.7
|
128
|
+
signing_key:
|
129
|
+
specification_version: 2
|
130
|
+
summary: Rapleaf's goal is to make the internet safe and transparent, by allowing you to evaluate your web footprint across a variety of user-generated sites
|
131
|
+
test_files: []
|
132
|
+
|