faces 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,14 @@
1
+ Author: Nick Pellant <contact@nickpellant.com>
2
+ Copyright: (C) 2010 Silentale.com SAS
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
data/README.markdown ADDED
@@ -0,0 +1,201 @@
1
+ # Faces
2
+
3
+ <small>Avatars made easy, by [Nick Pellant](http://nickpellant.com).</small>
4
+
5
+ Faces is an avatar provider/management library. It allows developers to fetch avatars from multiple sources in a consistent manner. Faces was built to rectify a problem originally faced when improving the avatars system at [Silentale](http://silentale.com). Faces has default support for the following avatar sources:
6
+
7
+ * [Facebook](http://facebook.com)
8
+ * [Twitter](http://twitter.com) via [Tweet Images](http://tweetimag.es/)
9
+ * [Highrise](http://highrisehq.com)
10
+ * [Flickr](http:/flickr.com)
11
+ * [Gravatar](http://gravatar.com)
12
+
13
+ Faces is now available in both [Ruby](http://github.com/nickpellant/faces) and [PHP](http://github.com/nickpellant/faces-php) with a Python version in its way soon. As Faces is available in multiple languages provider support may vary from one project to another however it will be attempted to keep default provider support synchronized.
14
+
15
+ ## Public methods
16
+
17
+ avatar_url(identifier, provider, configuration = {})
18
+
19
+ The **avatar\_url** method is an accessor point to pull an avatar from a provider. The method will only return a value if the provider exists and the **url** method exists for the provider, otherwise it will return the default avatar url (**avatar\_default\_url**).
20
+
21
+ avatar_html(identifier, provider, configuration = {})
22
+
23
+ The **avatar\_html** method is an accessor point to pull an avatar from a provider and encase it in a img html tag. It will also add any configurations you've set regarding markup to the tag. The method will only return a value if the provider exists and the **html** method exists for the provider, otherwise it will return the default avatar html (**avatar\_default\_html**).
24
+
25
+ generate_html(url, configuration = {})
26
+
27
+ The **generate\_html** method allows you to pass an avatar URL for which a provider does not exist so as to use the Faces configuration architecture, allowing you to keep a level of consistency. (We do suggest however you build your own providers directly, as it's a hell of a lot cooler)
28
+
29
+ avatar_default_url(configuration = {})
30
+
31
+ The **avatar\_default\_url** method returns the default avatar url.
32
+
33
+ avatar_default_html(configuration = {})
34
+
35
+ The **avatar\_default\_html** method returns the default avatar html img tag.
36
+
37
+ avatar_exists?(identifier, provider, configuration = {})
38
+
39
+ The **avatar\_exists?** method returns true/false as to whether an avatar exists for the given details.
40
+
41
+ provider_exists?(provider)
42
+
43
+ The **provider\_exists?** method returns true/false as to whether a provider with the given string exists and is available.
44
+
45
+ provider_method_exists?(method, provider)
46
+
47
+ The **provider\_method\_exists?** method returns true/false as to whether said method exists for said provider (also returns false if provider does not exist).
48
+
49
+ ### Note
50
+
51
+ Make sure to check out the relevant documentation for each provider. Providers are standardized as much as possible but there are sometimes special requirements (Flickr requires an API key in it's configuration, for example).
52
+
53
+ ## Installation
54
+
55
+ Install the gem (**Recommended**)
56
+
57
+ sudo gem install faces
58
+
59
+ ### Ruby on Rails
60
+
61
+ Add this to your `environment.rb` (gem setup only)
62
+
63
+ config.gem 'faces', :version => '>= x.x'
64
+
65
+ If you don't like gems for some reason, install it as a plugin
66
+
67
+ script/plugin install git://github.com/nickpellant/faces.git
68
+
69
+ We also suggest you setup your configuration via an initializer (find an example file on how to do this in the 'examples/rails' folder)
70
+
71
+ ## Configuration options
72
+
73
+ Faces has a hierarchy system for configuration. We start of with a universal configuration and gradually override as we go down the chain like so:
74
+
75
+ **Custom Configuration (method set)** > **Provider Configuration** > **Universal Configuration**
76
+
77
+ Faces by default sets a whole bunch of values for provider & universal configurations, but we highly recommend you change them to suit your needs. I've listed the universal ones below and provider specific configuration options with their provider documentations.
78
+
79
+ * ::Faces::Configuration::UNIVERSAL
80
+ * Fallback avatar url (string)
81
+ * :default => 'http://www.gravatar.com/avatar/?d=identicon'
82
+ * Max dimension constraints for width/height of avatar (integer)
83
+ * :size => 50
84
+ * Universally assigned classes to all avatars (string)
85
+ * :html\_classes => 'faces avatars'
86
+ * Use secure connection where possible (boolean)
87
+ * :html\_classes => false
88
+ * Restrict dimensions, to activate set 'square-only' (string)
89
+ * :dimension\_restriction => ''
90
+
91
+ ## Facebook Provider
92
+
93
+ The Facebook provider supports all the functionality available from it's API. It supports only **html** calls however (which are, in fact FBML, but we keep the name for sake of consistency).
94
+
95
+ There are a few additional configuration options available for Facebook that you may want to look at.
96
+
97
+ * ::Faces::Configuration::FACEBOOK
98
+ * Layer facebook logo ontop of avatar (boolean)
99
+ * :facebook\_logo => false
100
+ * Auto-link avatar back to Facebook (boolean)
101
+ * :facebook\_auto\_linked => false
102
+ * Provider specific html classes (string)
103
+ * :html\_provider\_classes => 'facebook'
104
+
105
+ To get this provider working you will also need a Facebook application/API key (this is because the provider uses FBML to generate it's avatars).
106
+
107
+ Once you have the application & API key add the following before the close of your body tag
108
+
109
+ <script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php/en_GB" type="text/javascript"></script>
110
+ <script type="text/javascript">FB.init("INSERT PUBLIC API KEY HERE");</script>
111
+
112
+ Make sure you have setup Facebook Connect for your Facebook application with the site url and base url in the application settings. If they are setup incorrectly this will not work!
113
+
114
+ You will also need to add the following to your html tag to complete the setup
115
+
116
+ xmlns:fb="http://www.facebook.com/2008/fbml"
117
+
118
+ Facebook avatar sizes are calculated dynamically from your configuration. Available sizes are 50x50, <=100 and >100. Faces calculates which of the available sizes provided by facebook best matches the dimensions you provided. If you select to receive only square images but choose a size over 50x50 there will be pixilation.
119
+
120
+ ### Further reading
121
+
122
+ * [Full Facebook provider documentation](http://nickpellant.com/open-source/faces/ruby/provider/facebook)
123
+ * [Fb:profile-pic Documentation](http://wiki.developers.facebook.com/index.php/Fb:profile-pic)
124
+
125
+ ## Twitter Provider
126
+
127
+ The Twitter provider uses the [Tweet Images](http://tweetimag.es/) mapper to provide urls (an awesome project from [Joe Stump](http://stu.mp)). It supports both **html** and **url** calls.
128
+
129
+ There are a few additional configuration options available for Gravatar that you may want to look at.
130
+
131
+ * ::Faces::Configuration::TWITTER
132
+ * Provider specific html classes (string)
133
+ * :html\_provider\_classes => 'gravatar'
134
+
135
+ Twitter avatar sizes are calculated dynamically from your configuration. Available sizes are 24x24, 48x48, 73x73 and the original size. Faces calculates which of the available sizes provided by twitter best matches the dimensions you provided. If you select to receive only square images but choose a size over 73x73 you will be given the largest possible square avatar.
136
+
137
+ ### Further reading
138
+
139
+ * [Full Gravatar provider documentation](http://nickpellant.com/open-source/faces/ruby/provider/gravatar)
140
+ * [Tweet Images](http://tweetimag.es/)
141
+
142
+ ## Highrise Provider
143
+
144
+ Supports both **html** and **url** calls.
145
+
146
+ Highrise expects a **contact\_id** as it's identifier parameter. It also expects the configuration option :highrise\_account\_name to be set appropriately.
147
+
148
+ <small>_for those who do not know the account name for highrise is the subdomain, i.e. myaccountname.highrisehq.com_</small>
149
+
150
+ There are a few additional configuration options available for Highrise that you may want to look at.
151
+
152
+ * ::Faces::Configuration::FLICKR
153
+ * Provider specific html classes (string)
154
+ * :html\_provider\_classes => 'flickr'
155
+
156
+ Highrise avatar sizes are calculated dynamically from your configuration. Available sizes are 32x32 and 53x53. Faces calculates which of the available sizes provided by Highrise best matches the dimensions you provided.
157
+
158
+ ### Further reading
159
+
160
+ * [Full Highrise provider documentation](http://nickpellant.com/open-source/faces/ruby/provider/highrise)
161
+ * [Highrise API](http://developer.37signals.com/highrise/)
162
+
163
+ ## Flickr Provider
164
+
165
+ The Flickr provider supports all the functionality of the API. It supports both **html** and **url** calls.
166
+
167
+ To have the Flickr provider working you will _need_ to set an API key.
168
+
169
+ * ::Faces::Configuration::FLICKR
170
+ * API key of application on Flickr (string)
171
+ * :flickr\_api\_key => 'dzgasgji3ewaojodsgojw'
172
+
173
+ There are a few additional configuration options available for Flickr that you may want to look at.
174
+
175
+ * ::Faces::Configuration::FLICKR
176
+ * Provider specific html classes (string)
177
+ * :html\_provider\_classes => 'flickr'
178
+
179
+ Flickr only provides avatars at 48x48 - if you're using a higher size than this there will be pixilation.
180
+
181
+ ### Further reading
182
+
183
+ * [Full Flickr provider documentation](http://nickpellant.com/open-source/faces/ruby/provider/flickr)
184
+ * [Flickr Buddyicons](http://www.flickr.com/services/api/misc.buddyicons.html)
185
+
186
+ ## Gravatar Provider
187
+
188
+ The Gravatar provider supports all the functionality available from it's API. It supports both **html** and **url** calls.
189
+
190
+ There are a few additional configuration options available for Gravatar that you may want to look at.
191
+
192
+ * ::Faces::Configuration::GRAVATAR
193
+ * Gravatar rating, minimum requirement (string)
194
+ * :gravatar\_rating => 'G'
195
+ * Provider specific html classes (string)
196
+ * :html\_provider\_classes => 'gravatar'
197
+
198
+ ### Further reading
199
+
200
+ * [Full Gravatar provider documentation](http://nickpellant.com/open-source/faces/ruby/provider/gravatar)
201
+ * [Gravatar URL construction](http://en.gravatar.com/site/implement/url)
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gemspec|
7
+ gemspec.name = "faces"
8
+ gemspec.summary = "Faces manages external and internal avatar sources in one unified format."
9
+ gemspec.description = "Avatars made super simple."
10
+ gemspec.email = "nick@silentale.com"
11
+ gemspec.homepage = "http://github.com/nickpellant/faces"
12
+ gemspec.authors = ["Nick Pellant"]
13
+ end
14
+ Jeweler::GemcutterTasks.new
15
+ rescue LoadError
16
+ puts "Jeweler not available. Install it with: sudo gem install jeweler -s http://gemcutter.org"
17
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.5.0
data/faces.gemspec ADDED
@@ -0,0 +1,65 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{faces}
8
+ s.version = "0.5.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Nick Pellant"]
12
+ s.date = %q{2010-03-15}
13
+ s.description = %q{Avatars made super simple.}
14
+ s.email = %q{nick@silentale.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.markdown"
18
+ ]
19
+ s.files = [
20
+ "LICENSE",
21
+ "README.markdown",
22
+ "Rakefile",
23
+ "VERSION",
24
+ "faces.gemspec",
25
+ "init.rb",
26
+ "lib/faces.rb",
27
+ "lib/providers/facebook.rb",
28
+ "lib/providers/flickr.rb",
29
+ "lib/providers/gravatar.rb",
30
+ "lib/providers/highrise.rb",
31
+ "lib/providers/twitter.rb",
32
+ "test/providers/test_facebook.rb",
33
+ "test/providers/test_flickr.rb",
34
+ "test/providers/test_gravatar.rb",
35
+ "test/providers/test_highrise.rb",
36
+ "test/providers/test_twitter.rb",
37
+ "test/test_faces.rb",
38
+ "test/test_helper.rb"
39
+ ]
40
+ s.homepage = %q{http://github.com/nickpellant/faces}
41
+ s.rdoc_options = ["--charset=UTF-8"]
42
+ s.require_paths = ["lib"]
43
+ s.rubygems_version = %q{1.3.6}
44
+ s.summary = %q{Faces manages external and internal avatar sources in one unified format.}
45
+ s.test_files = [
46
+ "test/providers/test_facebook.rb",
47
+ "test/providers/test_flickr.rb",
48
+ "test/providers/test_gravatar.rb",
49
+ "test/providers/test_highrise.rb",
50
+ "test/providers/test_twitter.rb",
51
+ "test/test_faces.rb",
52
+ "test/test_helper.rb"
53
+ ]
54
+
55
+ if s.respond_to? :specification_version then
56
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
57
+ s.specification_version = 3
58
+
59
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
60
+ else
61
+ end
62
+ else
63
+ end
64
+ end
65
+
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'faces'
data/lib/faces.rb ADDED
@@ -0,0 +1,104 @@
1
+ Dir.glob(File.join(File.dirname(__FILE__), '/providers/*.rb')).each { |f| require f }
2
+
3
+ require 'net/http'
4
+ require 'net/https'
5
+ require 'rexml/document'
6
+ require 'digest/md5'
7
+
8
+ module Faces
9
+ module Configuration
10
+ # Universal configuration for avatars
11
+ UNIVERSAL = {
12
+ # Avatar to default to
13
+ :default => 'http://www.gravatar.com/avatar/?d=identicon',
14
+ # Max height or width pixel size for returned avatar
15
+ :size => 50,
16
+ # CSS classes to be assigned to all <img /> tags
17
+ :html_classes => 'faces avatar',
18
+ # Use a secure connection when one is available
19
+ :use_secure => false,
20
+ # If we only ever want to return square images, set to square-only
21
+ :dimension_restriction => ''
22
+ }
23
+ end
24
+ module Public
25
+ # Returns the avatar in an <img /> HTML tag based on identifier, provider and configuration
26
+ # Uses local provider classes to generate the result
27
+ # Does not check for existance of Avatar, this is the responsibility of the developer
28
+ def avatar_html(identifier, provider, configuration = {})
29
+ if provider_method_exists?('html', provider)
30
+ obj = "::Faces::Providers::#{provider.to_s.classify}".constantize.new
31
+ obj.html(identifier, configuration)
32
+ else
33
+ avatar_default_html(configuration)
34
+ end
35
+ end
36
+ # Returns avatar url based on identifier, provider and configuration
37
+ # Uses local provider classes to generate the result
38
+ # Does not check for existance of Avatar, this is the responsibility of the developer
39
+ def avatar_url(identifier, provider, configuration = {})
40
+ if provider_method_exists?('url', provider)
41
+ obj = "::Faces::Providers::#{provider.to_s.classify}".constantize.new
42
+ obj.url(identifier, configuration)
43
+ else
44
+ avatar_default_url(configuration)
45
+ end
46
+ end
47
+ # Returns true if avatar exists, false if not
48
+ def avatar_exists?(identifier, provider, configuration = {})
49
+ obj = "::Faces::Providers::#{provider.to_s.classify}".constantize.new
50
+ obj.exists?(identifier, configuration)
51
+ end
52
+ # Returns the default avatar in an <img /> HTML tag
53
+ def avatar_default_html(configuration = {})
54
+ url = configuration[:default].present? ? configuration[:default] : ::Faces::Configuration::UNIVERSAL[:default]
55
+ generate_html(url, configuration)
56
+ end
57
+ # Returns the default avatar as a url
58
+ def avatar_default_url(configuration = {})
59
+ configuration[:default].present? ? configuration[:default] : ::Faces::Configuration::UNIVERSAL[:default]
60
+ end
61
+ # Returns true if provider exists, false if not
62
+ def provider_exists?(provider)
63
+ true if ::Faces::Providers.const_get("#{provider.to_s.classify}")
64
+ rescue NameError
65
+ false
66
+ end
67
+ # Returns true if provider method exists, false if not
68
+ def provider_method_exists?(method, provider)
69
+ if ::Faces::Providers.const_get("#{provider.to_s.classify}")
70
+ obj = "::Faces::Providers::#{provider.to_s.classify}".constantize.new
71
+ obj.respond_to?(method)
72
+ end
73
+ rescue NameError
74
+ false
75
+ end
76
+ # Generates a HTML <img /> tag for the given url
77
+ def generate_html(url, configuration = {})
78
+ m_configuration = Faces::Common.merge_configurations([Faces::Configuration::UNIVERSAL, configuration])
79
+ combined_classes = m_configuration[:html_provider_classes].present? ? m_configuration[:html_classes] + ' ' + m_configuration[:html_provider_classes] : m_configuration[:html_classes]
80
+
81
+ html = '<img src="' + url + '" class="' + combined_classes + '"'
82
+ html += 'id="' + m_configuration[:id] + '"' if m_configuration[:id].present?
83
+ html += ' />'
84
+ end
85
+
86
+ module_function :avatar_exists?, :provider_exists?, :provider_method_exists?, :avatar_url, :avatar_html, :generate_html, :avatar_default_html, :avatar_default_url
87
+ end
88
+ module Common
89
+ # Merges together all configurations given from first to last in order of priority
90
+ def merge_configurations(configurations)
91
+ configuration = Faces::Configuration::UNIVERSAL
92
+ configurations.each do |config|
93
+ configuration = configuration.merge(config)
94
+ end
95
+ configuration
96
+ end
97
+ # Builds a url query parameter string
98
+ def build_param(key, value, first = false)
99
+ value.present? ? (first == true ? "?#{key}=#{value}" : "&#{key}=#{value}") : ''
100
+ end
101
+
102
+ module_function :merge_configurations, :build_param
103
+ end
104
+ end
@@ -0,0 +1,52 @@
1
+ module Faces
2
+ module Configuration
3
+ # Configuration for facebook avatars
4
+ FACEBOOK = {
5
+ # Show facebook logo
6
+ :facebook_logo => false,
7
+ # Additional HTML classes specific to Facebook provider (merged with :html_classes)
8
+ :html_provider_classes => 'facebook',
9
+ # Link back to Facebook automatically?
10
+ :facebook_auto_linked => false
11
+ }
12
+ end
13
+ module Providers
14
+ # Facebook class handles all Facebook based avatar methods, check the information page for more details:
15
+ # http://nickpellant.com/open-source/faces/ruby/providers/facebook
16
+ #
17
+ # Default required methods for providers are +url+ and/or +html+, +exists?+
18
+ # All other methods are at the discretion of the developer
19
+ # Check the provider creation guide for more details:
20
+ # http://nickpellant.com/open-source/faces/ruby/developing-providers
21
+ class Facebook
22
+ # Constructs FBML tag for avatar
23
+ def html(user_id, configuration = {})
24
+ m_configuration = Faces::Common.merge_configurations([Faces::Configuration::FACEBOOK, configuration])
25
+ fbml = '<fb:profile-pic uid="' + user_id + '" facebook-logo="' + m_configuration[:facebook_logo].to_s + '" linked="' + m_configuration[:facebook_auto_linked].to_s +
26
+ '" size="' + size(m_configuration) + '" class="' + m_configuration[:html_classes] + ' ' + m_configuration[:html_provider_classes] + '"'
27
+ fbml += m_configuration[:html_id] if m_configuration[:html_id].present?
28
+ fbml += '"></fb:profile-pic>'
29
+ end
30
+ # Botch job as it's not possible to check for FBML avatar presence :(
31
+ def exists?(identifier, configuration = {}); true; end
32
+ private
33
+ # Calculates the size of image to pull from Facebook
34
+ # This is decided based on the configuration settings of Faces
35
+ def size(m_configuration = {})
36
+ # Square avatar
37
+ if m_configuration[:size] <= 50
38
+ 'square'
39
+ # Small avatar
40
+ elsif m_configuration[:size] <= 100 && m_configuration[:dimension_restriction] != 'square-only'
41
+ 'small'
42
+ # Normal size
43
+ elsif m_configuration[:size] > 100 && m_configuration[:dimension_restriction] != 'square-only'
44
+ 'normal'
45
+ # Default back to square
46
+ else
47
+ 'square'
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,54 @@
1
+ module Faces
2
+ module Configuration
3
+ # Configuration for Flickr avatars
4
+ FLICKR = {
5
+ # Required to use the Flickr provider
6
+ :flickr_api_key => '',
7
+ # Additional HTML classes specific to Twitter provider (merged with :html_classes)
8
+ :html_provider_classes => 'twitter'
9
+ }
10
+ end
11
+ module Providers
12
+ # Flickr class handles all Flickr based avatar methods, check the information page for more details:
13
+ # http://nickpellant.com/open-source/faces/ruby/providers/flickr
14
+ #
15
+ # Default required methods for providers are +url+ and/or +html+, +exists?+
16
+ # All other methods are at the discretion of the developer
17
+ # Check the provider creation guide for more details:
18
+ # http://nickpellant.com/open-source/faces/ruby/developing-providers
19
+ class Flickr
20
+ # Constructs Flickr url from user_id/configuration
21
+ def url(user_id, configuration = {})
22
+ m_configuration = Faces::Common.merge_configurations([Faces::Configuration::FLICKR, configuration])
23
+ hostname(flickr_avatar_details(user_id, m_configuration)) + user_id + '.jpg'
24
+ end
25
+ # Constructs HTML <img /> tag for Flickr
26
+ def html(user_id, configuration = {})
27
+ m_configuration = Faces::Common.merge_configurations([Faces::Configuration::FLICKR, configuration])
28
+ Faces::Public.generate_html(url(user_id, configuration), m_configuration)
29
+ end
30
+ # Checks Avatar exists
31
+ def exists?(user_id, configuration = {})
32
+ url = URI.parse(url(user_id, configuration))
33
+ http = Net::HTTP.new(url.host, url.port)
34
+ http.use_ssl = (url.scheme == 'https')
35
+ request = Net::HTTP::Get.new(url.path)
36
+ response = http.request(request)
37
+ response.code == '200' ? true : false
38
+ end
39
+ private
40
+ # Fetches the buddyicon farm details based on the user_id given
41
+ # An avatar can not be pulled from Flickr without this method
42
+ def flickr_avatar_details(user_id, m_configuration = {})
43
+ url = URI.parse('http://api.flickr.com/services/rest/?method=flickr.people.getInfo&api_key=' + m_configuration[:flickr_api_key] + '&user_id=' + user_id)
44
+ xml = Net::HTTP.get_response(url).body
45
+ doc = REXML::Document.new(xml)
46
+ { :icon_server => doc.root.elements['person'].attributes['iconserver'], :icon_farm => doc.root.elements['person'].attributes['iconfarm'] }
47
+ end
48
+ # Constructs appropriate hostname based on return of flickr_avatar_details
49
+ def hostname(flickr_details)
50
+ 'http://farm' + flickr_details[:icon_farm] + '.static.flickr.com/' + flickr_details[:icon_server] + '/buddyicons/'
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,63 @@
1
+ module Faces
2
+ module Configuration
3
+ # Configuration for Gravatar avatars
4
+ GRAVATAR = {
5
+ # Apply a Gravatar rating requirement ('G', 'PG', 'R', 'X')
6
+ # We default to 'G' to remain consistant with Gravatar
7
+ :gravatar_rating => 'G',
8
+ # Additional HTML classes specific to Gravatar provider (merged with :html_classes)
9
+ :html_provider_classes => 'gravatar'
10
+ }
11
+ end
12
+ module Providers
13
+ # Gravatar class handles all Gravatar based avatar methods, check the information page for more details:
14
+ # http://nickpellant.com/open-source/faces/ruby/providers/gravatar
15
+ #
16
+ # Default required methods for providers are +url+ and/or +html+, +exists?+
17
+ # All other methods are at the discretion of the developer
18
+ # Check the provider creation guide for more details:
19
+ # http://nickpellant.com/open-source/faces/ruby/developing-providers
20
+ class Gravatar
21
+ # Constructs Gravatar url from email/configuration
22
+ # It can be passed either an MD5 hash as email or a string email
23
+ def url(email, configuration = {})
24
+ m_configuration = Faces::Common.merge_configurations([Faces::Configuration::GRAVATAR, configuration])
25
+ email = md5_email(email) if email.include? "@"
26
+ url = hostname(m_configuration) + email + build_params_string(m_configuration)
27
+ end
28
+ # Constructs HTML <img /> tag for Gravatar
29
+ def html(email, configuration = {})
30
+ m_configuration = Faces::Common.merge_configurations([Faces::Configuration::GRAVATAR, configuration])
31
+ Faces::Public.generate_html(url(email, configuration), m_configuration)
32
+ end
33
+ # Checks Avatar exists
34
+ def exists?(email, configuration = {})
35
+ m_configuration = Faces::Common.merge_configurations([Faces::Configuration::GRAVATAR, configuration, {:default => '404'}])
36
+ url = URI.parse(url(email, m_configuration))
37
+ http = Net::HTTP.new(url.host, url.port)
38
+ http.use_ssl = (url.scheme == 'https')
39
+ request = Net::HTTP::Get.new(url.path + '?' + url.query)
40
+ response = http.request(request)
41
+ response.code == '200' ? true : false
42
+ end
43
+ # Formats email and converts into MD5 hash for use with Gravatar url
44
+ def md5_email(email)
45
+ Digest::MD5.hexdigest(email.strip.downcase)
46
+ end
47
+ private
48
+ # Constructs appropriate hostname based on secure preferences
49
+ def hostname(m_configuration = {})
50
+ 'http' + (m_configuration[:use_secure] ? 's://secure.' : '://') + 'gravatar.com/avatar/'
51
+ end
52
+ # Build url parameters string
53
+ def build_params_string(m_configuration = {})
54
+ # Set the size of the avatar we want to fetch
55
+ Faces::Common.build_param('s', m_configuration[:size], true) +
56
+ # Set the rating of the avatar we want to fetch
57
+ Faces::Common.build_param('r', m_configuration[:gravatar_rating]) +
58
+ # Default image to defer too (or possibily a generator in the case of Gravatar)
59
+ Faces::Common.build_param('d', m_configuration[:default])
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,49 @@
1
+ module Faces
2
+ module Configuration
3
+ # Configuration for highrise avatars
4
+ HIGHRISE = {
5
+ # Base account name (http://accountname.highrisehq.com)
6
+ :highrise_account_name => '',
7
+ # Additional HTML classes specific to Highrise provider (merged with :html_classes)
8
+ :html_provider_classes => 'highrise'
9
+ }
10
+ end
11
+ module Providers
12
+ # Highrise class handles all Highrise based avatar methods
13
+ # Default required methods for providers are +url+ and/or +html+, +exists?+
14
+ # All other methods are at the discretion of the developer
15
+ # Check the provider creation guide for more details:
16
+ # http://nickpellant.com/open-source/faces/ruby/developing-providers
17
+ class Highrise
18
+ # Constructs Highrise url from contact_id/configuration
19
+ def url(contact_id, configuration = {})
20
+ m_configuration = Faces::Common.merge_configurations([Faces::Configuration::HIGHRISE, configuration])
21
+ hostname(m_configuration) + contact_id[0..3] + '/' + contact_id[4..-1] + '-' + size(m_configuration) + '.png'
22
+ end
23
+ # Constructs HTML <img /> tag for Highrise avatar
24
+ def html(contact_id, configuration = {})
25
+ m_configuration = Faces::Common.merge_configurations([Faces::Configuration::HIGHRISE, configuration])
26
+ Faces::Public.generate_html(url(contact_id, configuration), m_configuration)
27
+ end
28
+ # Checks Avatar exists
29
+ def exists?(contact_id, configuration = {})
30
+ url = URI.parse(url(contact_id, configuration))
31
+ http = Net::HTTP.new(url.host, url.port)
32
+ http.use_ssl = (url.scheme == 'https')
33
+ request = Net::HTTP::Get.new(url.path)
34
+ response = http.request(request)
35
+ response.code == '200' ? true : false
36
+ end
37
+ private
38
+ # Constructs appropriate hostname based on secure preferences and account name
39
+ def hostname(m_configuration)
40
+ 'http' + (m_configuration[:use_secure] ? 's' : '') + "://" + m_configuration[:highrise_account_name] + ".highrisehq.com/dl/avatars/person/"
41
+ end
42
+ # Calculates the size of image to pull from Highrise
43
+ # This is decided based on the configuration settings of Faces
44
+ def size(m_configuration)
45
+ m_configuration[:size] <= 32 ? 'small' : 'large'
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,60 @@
1
+ module Faces
2
+ module Configuration
3
+ # Configuration for Twitter avatars
4
+ TWITTER = {
5
+ # Additional HTML classes specific to Twitter provider (merged with :html_classes)
6
+ :html_provider_classes => 'twitter'
7
+ }
8
+ end
9
+ module Providers
10
+ # Twitter class handles all Twitter based avatar methods, check the information page for more details:
11
+ # http://nickpellant.com/open-source/faces/ruby/providers/twitter
12
+ #
13
+ # Default required methods for providers are +url+ and/or +html+, +exists?+
14
+ # All other methods are at the discretion of the developer
15
+ # Check the provider creation guide for more details:
16
+ # http://nickpellant.com/open-source/faces/ruby/developing-providers
17
+ class Twitter
18
+ # Constructs Twitter url from username/configuration
19
+ def url(username, configuration = {})
20
+ m_configuration = Faces::Common.merge_configurations([Faces::Configuration::TWITTER, configuration])
21
+ 'http://img.tweetimag.es/i/' + username + '_' + size(m_configuration)
22
+ end
23
+ # Constructs HTML <img /> tag for Twitter
24
+ def html(username, configuration = {})
25
+ m_configuration = Faces::Common.merge_configurations([Faces::Configuration::TWITTER, configuration])
26
+ Faces::Public.generate_html(url(username, configuration), m_configuration)
27
+ end
28
+ # Checks Avatar exists
29
+ def exists?(username, configuration = {})
30
+ url = URI.parse(url(username, configuration))
31
+ http = Net::HTTP.new(url.host, url.port)
32
+ http.use_ssl = (url.scheme == 'https')
33
+ request = Net::HTTP::Get.new(url.path)
34
+ response = http.request(request)
35
+ response.code == '200' ? true : false
36
+ end
37
+ private
38
+ # Calculates the size of image to pull from Twitter
39
+ # This is decided based on the configuration settings of Faces
40
+ def size(m_configuration = {})
41
+ # Mini sized
42
+ if m_configuration[:size] <= 24
43
+ 'm'
44
+ # Normal sized
45
+ elsif m_configuration[:size] <= 48
46
+ 'n'
47
+ # Large sized
48
+ elsif m_configuration[:size] <= 73
49
+ 'b'
50
+ # Originally uploaded image
51
+ elsif m_configuration[:size] > 73 && m_configuration[:dimension_restriction] != 'square-only'
52
+ 'o'
53
+ # Default back to large size for anything above 73px but still square requirement
54
+ else
55
+ 'b'
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,36 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class FacebookTest < Test::Unit::TestCase
4
+
5
+ ####################
6
+ #--- html ---#
7
+ ####################
8
+ def test_html_should_return_facebook_html
9
+ obj = ::Faces::Providers::Facebook.new
10
+ html = obj.html('711246611')
11
+ assert_match '<fb:profile-pic uid="', html
12
+ end
13
+
14
+ ####################
15
+ #--- size ---#
16
+ ####################
17
+ def test_size_should_return_square
18
+ obj = ::Faces::Providers::Facebook.new
19
+ assert_equal 'square', obj.__send__(:size, {:size => 50})
20
+ end
21
+
22
+ def test_size_should_return_small
23
+ obj = ::Faces::Providers::Facebook.new
24
+ assert_equal 'small', obj.__send__(:size, {:size => 100})
25
+ end
26
+
27
+ def test_size_should_return_normal
28
+ obj = ::Faces::Providers::Facebook.new
29
+ assert_equal 'normal', obj.__send__(:size, {:size => 150})
30
+ end
31
+
32
+ def test_size_should_return_square_when_set_to_square_only
33
+ obj = ::Faces::Providers::Facebook.new
34
+ assert_equal 'square', obj.__send__(:size, {:size => 150, :dimension_restriction => 'square-only'})
35
+ end
36
+ end
@@ -0,0 +1,33 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class FlickrTest < Test::Unit::TestCase
4
+
5
+ ####################
6
+ #--- url ---#
7
+ ####################
8
+ def test_url_should_return_non_secure_flickr_url
9
+ obj = ::Faces::Providers::Flickr.new
10
+ url = obj.url('12037949754@N01', {:flickr_api_key => '5ad55b17c6964b3c83651522576af9ca'})
11
+ assert_match 'static.flickr.com', url
12
+ assert_match 'http://farm', url
13
+ end
14
+
15
+ ####################
16
+ #--- html ---#
17
+ ####################
18
+ def test_html_should_return_non_secure_flickr_html
19
+ obj = ::Faces::Providers::Flickr.new
20
+ html = obj.html('12037949754@N01', {:flickr_api_key => '5ad55b17c6964b3c83651522576af9ca'})
21
+ assert_match 'static.flickr.com', html
22
+ assert_match '<img src="http://farm', html
23
+ end
24
+
25
+ ####################
26
+ #--- exists? ---#
27
+ ####################
28
+ def test_exists_should_return_true_if_avatar_exists
29
+ obj = ::Faces::Providers::Flickr.new
30
+ result = obj.exists?('12037949754@N01', {:flickr_api_key => '5ad55b17c6964b3c83651522576af9ca'})
31
+ assert_equal true, result, 'Avatar does exist, should have returned true'
32
+ end
33
+ end
@@ -0,0 +1,88 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class GravatarTest < Test::Unit::TestCase
4
+
5
+ ####################
6
+ #--- url ---#
7
+ ####################
8
+ def test_url_should_return_non_secure_gravatar_url
9
+ obj = ::Faces::Providers::Gravatar.new
10
+ url = obj.url('da9658571a8ca10cf8b0f91625a8c3d5')
11
+ assert_match 'http://gravatar.com/avatar', url
12
+ end
13
+
14
+ def test_url_should_return_secure_gravatar_url
15
+ obj = ::Faces::Providers::Gravatar.new
16
+ url = obj.url('da9658571a8ca10cf8b0f91625a8c3d5', {:use_secure => true})
17
+ assert_match 'https://secure.gravatar.com/avatar', url
18
+ end
19
+
20
+ ####################
21
+ #--- html ---#
22
+ ####################
23
+ def test_html_should_return_non_secure_gravatar_image_html
24
+ obj = ::Faces::Providers::Gravatar.new
25
+ html = obj.html('da9658571a8ca10cf8b0f91625a8c3d5')
26
+ assert_match '<img src="http://gravatar.com/', html
27
+ end
28
+
29
+ def test_html_should_return_secure_gravatar_image_html
30
+ obj = ::Faces::Providers::Gravatar.new
31
+ html = obj.html('da9658571a8ca10cf8b0f91625a8c3d5', {:use_secure => true})
32
+ assert_match '<img src="https://secure.gravatar.com/', html
33
+ end
34
+
35
+ def test_html_should_work_with_string_emails
36
+ obj = ::Faces::Providers::Gravatar.new
37
+ html = obj.html('someone@something.com')
38
+ assert_match '<img src="http://gravatar.com/', html
39
+ end
40
+
41
+ ####################
42
+ #--- exists? ---#
43
+ ####################
44
+ def test_exists_should_return_false_if_avatar_doesnt_exist
45
+ obj = ::Faces::Providers::Gravatar.new
46
+ result = obj.exists?('someone@example.com')
47
+ assert_equal false, result, 'Avatar does not exist, should have returned false'
48
+ end
49
+
50
+ def test_exists_should_return_true_if_avatar_exists
51
+ obj = ::Faces::Providers::Gravatar.new
52
+ result = obj.exists?('da9658571a8ca10cf8b0f91625a8c3d5')
53
+ assert_equal true, result, 'Avatar exists, should have returned true'
54
+ end
55
+
56
+ def test_exists_should_return_false_if_avatar_doesnt_exist_on_secure
57
+ obj = ::Faces::Providers::Gravatar.new
58
+ result = obj.exists?('someone@example.com', {:use_secure => true})
59
+ assert_equal false, result, 'Avatar does not exist, should have returned false'
60
+ end
61
+
62
+ def test_exists_should_return_true_if_avatar_does_exist_on_secure
63
+ obj = ::Faces::Providers::Gravatar.new
64
+ result = obj.exists?('da9658571a8ca10cf8b0f91625a8c3d5', {:use_secure => true})
65
+ assert_equal true, result, 'Avatar does exist, should have returned true'
66
+ end
67
+ ####################
68
+ #--- md5_email ---#
69
+ ####################
70
+ def test_md5_email_should_return_correct_md5_hash
71
+ obj = ::Faces::Providers::Gravatar.new
72
+ result = obj.md5_email(' soMEonE@exaMPle.com ')
73
+ assert_equal Digest::MD5.hexdigest('someone@example.com'), result, 'MD5 has does not match correctly'
74
+ end
75
+
76
+ ####################
77
+ #--- hostname ---#
78
+ ####################
79
+ def test_hostname_should_return_non_secure_hostname
80
+ obj = ::Faces::Providers::Gravatar.new
81
+ assert_match 'http://gravatar.com', obj.__send__(:hostname, {:use_secure => false})
82
+ end
83
+
84
+ def test_hostname_should_return_secure_hostname
85
+ obj = ::Faces::Providers::Gravatar.new
86
+ assert_match 'https://secure.gravatar.com', obj.__send__(:hostname, {:use_secure => true})
87
+ end
88
+ end
@@ -0,0 +1,73 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class HighriseTest < Test::Unit::TestCase
4
+
5
+ ####################
6
+ #--- url ---#
7
+ ####################
8
+ def test_url_should_return_non_secure_highrise_url
9
+ obj = ::Faces::Providers::Highrise.new
10
+ url = obj.url('31479012', {:highrise_account_name => 'silentaletest'})
11
+ assert_match 'http://silentaletest.highrisehq.com/dl/avatars/person/3147/9012', url
12
+ end
13
+
14
+ def test_url_should_return_secure_highrise_url
15
+ obj = ::Faces::Providers::Highrise.new
16
+ url = obj.url('31479012', {:highrise_account_name => 'silentaletest', :use_secure => true})
17
+ assert_match 'https://silentaletest.highrisehq.com/dl/avatars/person/3147/9012', url
18
+ end
19
+
20
+ ####################
21
+ #--- html ---#
22
+ ####################
23
+ def test_html_should_return_non_secure_highrise_image
24
+ obj = ::Faces::Providers::Highrise.new
25
+ html = obj.html('31479012', {:highrise_account_name => 'silentaletest'})
26
+ assert_match '<img src="http://silentaletest.highrisehq.com/dl/avatars/person/3147/9012', html
27
+ end
28
+
29
+ def test_html_should_return_secure_highrise_image
30
+ obj = ::Faces::Providers::Highrise.new
31
+ html = obj.html('31479012', {:highrise_account_name => 'silentaletest', :use_secure => true})
32
+ assert_match '<img src="https://silentaletest.highrisehq.com/dl/avatars/person/3147/9012', html
33
+ end
34
+
35
+ ####################
36
+ #--- exists? ---#
37
+ ####################
38
+ def test_exists_should_return_true_if_avatar_exists_non_secure
39
+ obj = ::Faces::Providers::Highrise.new
40
+ result = obj.exists?('31479012', {:highrise_account_name => 'silentaletest', :use_secure => true})
41
+ assert_equal true, result, 'Avatar does exist, should have returned true'
42
+ end
43
+
44
+ def test_exists_should_return_true_if_avatar_exists_secure
45
+ obj = ::Faces::Providers::Highrise.new
46
+ result = obj.exists?('31479012', {:highrise_account_name => 'silentaletest', :use_secure => true})
47
+ assert_equal true, result, 'Avatar does exist, should have returned true'
48
+ end
49
+
50
+ def test_exists_should_return_false_if_avatar_doesnt_exist_non_secure
51
+ obj = ::Faces::Providers::Highrise.new
52
+ result = obj.exists?('31706827', {:highrise_account_name => 'silentaletest', :use_secure => true})
53
+ assert_equal false, result, 'Avatar doesn\'t exist, should have returned false'
54
+ end
55
+
56
+ def test_exists_should_return_false_if_avatar_doesnt_exist_secure
57
+ obj = ::Faces::Providers::Highrise.new
58
+ result = obj.exists?('31706827', {:highrise_account_name => 'silentaletest', :use_secure => true})
59
+ assert_equal false, result, 'Avatar doesn\'t exist, should have returned false'
60
+ end
61
+ ####################
62
+ #--- size ---#
63
+ ####################
64
+ def test_size_should_return_small
65
+ obj = ::Faces::Providers::Highrise.new
66
+ assert_equal 'small', obj.__send__(:size, {:size => 32})
67
+ end
68
+
69
+ def test_size_should_return_large
70
+ obj = ::Faces::Providers::Highrise.new
71
+ assert_equal 'large', obj.__send__(:size, {:size => 54})
72
+ end
73
+ end
@@ -0,0 +1,59 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class TwitterTest < Test::Unit::TestCase
4
+
5
+ ####################
6
+ #--- url ---#
7
+ ####################
8
+ def test_url_should_return_non_secure_tweetimages_url
9
+ obj = ::Faces::Providers::Twitter.new
10
+ url = obj.url('npellant')
11
+ assert_match 'http://img.tweetimag.es/i/', url
12
+ end
13
+
14
+ ####################
15
+ #--- html ---#
16
+ ####################
17
+ def test_html_should_return_twitter_image_html
18
+ obj = ::Faces::Providers::Twitter.new
19
+ html = obj.html('npellant')
20
+ assert_match '<img src="http://img.tweetimag.es/i/', html
21
+ end
22
+
23
+ ####################
24
+ #--- exists? ---#
25
+ ####################
26
+ def test_exists_should_return_true_if_avatar_exists
27
+ obj = ::Faces::Providers::Twitter.new
28
+ result = obj.exists?('npellant')
29
+ assert_equal true, result, 'Avatar does exist, should have returned true'
30
+ end
31
+
32
+ ####################
33
+ #--- size ---#
34
+ ####################
35
+ def test_size_should_return_mini
36
+ obj = ::Faces::Providers::Twitter.new
37
+ assert_equal 'm', obj.__send__(:size, {:size => 24})
38
+ end
39
+
40
+ def test_size_should_return_normal
41
+ obj = ::Faces::Providers::Twitter.new
42
+ assert_equal 'n', obj.__send__(:size, {:size => 48})
43
+ end
44
+
45
+ def test_size_should_return_big
46
+ obj = ::Faces::Providers::Twitter.new
47
+ assert_equal 'b', obj.__send__(:size, {:size => 73})
48
+ end
49
+
50
+ def test_size_should_return_original
51
+ obj = ::Faces::Providers::Twitter.new
52
+ assert_equal 'o', obj.__send__(:size, {:size => 100})
53
+ end
54
+
55
+ def test_size_should_return_big_when_set_to_square_only
56
+ obj = ::Faces::Providers::Twitter.new
57
+ assert_equal 'b', obj.__send__(:size, {:size => 100, :dimension_restriction => 'square-only'})
58
+ end
59
+ end
@@ -0,0 +1,60 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class FacesTest < Test::Unit::TestCase
4
+ def setup
5
+ end
6
+
7
+ ####################
8
+ #--- avatar_url ---#
9
+ ####################
10
+ def test_avatar_url_should_return_avatar_url_non_secure
11
+ url = Faces::Public.avatar_url('someone@something.com', 'gravatar')
12
+ assert_match 'http', url
13
+ end
14
+
15
+ def test_avatar_url_should_return_avatar_url_secure
16
+ url = Faces::Public.avatar_url('someone@something.com', 'gravatar', {:use_secure => true})
17
+ assert_match 'https', url
18
+ end
19
+
20
+ def test_avatar_url_should_return_default_when_provider_doesnt_exist
21
+ url = Faces::Public.avatar_url('someone@something.com', 'imnotreal')
22
+ assert_equal url, Faces::Public.avatar_default_url
23
+ end
24
+
25
+ def test_avatar_url_should_return_default_when_provider_method_doesnt_exist
26
+ url = Faces::Public.avatar_url('xyz', 'facebook')
27
+ assert_equal url, Faces::Public.avatar_default_url
28
+ end
29
+
30
+ #####################
31
+ #--- avatar_html ---#
32
+ #####################
33
+ def test_avatar_html_should_return_avatar_url_non_secure
34
+ url = Faces::Public.avatar_html('someone@something.com', 'gravatar')
35
+ assert_match 'http', url
36
+ end
37
+
38
+ def test_avatar_html_should_return_avatar_url_secure
39
+ url = Faces::Public.avatar_html('someone@something.com', 'gravatar', {:use_secure => true})
40
+ assert_match 'https', url
41
+ end
42
+
43
+ def test_avatar_html_should_return_default_when_provider_doesnt_exist
44
+ url = Faces::Public.avatar_html('someone@something.com', 'imnotreal')
45
+ assert_equal url, Faces::Public.avatar_default_html
46
+ end
47
+
48
+ ########################
49
+ #--- avatar_exists? ---#
50
+ ########################
51
+ def test_avatar_exists_should_return_true_when_an_avatar_exists
52
+ exists = Faces::Public.avatar_exists?('da9658571a8ca10cf8b0f91625a8c3d5', 'gravatar')
53
+ assert_equal exists, true
54
+ end
55
+
56
+ def test_avatar_exists_should_return_false_when_an_avatar_doesnt_exists
57
+ exists = Faces::Public.avatar_exists?('someone@something.com', 'gravatar')
58
+ assert_equal exists, false
59
+ end
60
+ end
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+ require 'test/unit'
4
+ require 'faces'
5
+
6
+ require 'net/http'
7
+ require 'rexml/document'
8
+ require 'digest/md5'
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: faces
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 5
8
+ - 0
9
+ version: 0.5.0
10
+ platform: ruby
11
+ authors:
12
+ - Nick Pellant
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-03-15 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: Avatars made super simple.
22
+ email: nick@silentale.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files:
28
+ - LICENSE
29
+ - README.markdown
30
+ files:
31
+ - LICENSE
32
+ - README.markdown
33
+ - Rakefile
34
+ - VERSION
35
+ - faces.gemspec
36
+ - init.rb
37
+ - lib/faces.rb
38
+ - lib/providers/facebook.rb
39
+ - lib/providers/flickr.rb
40
+ - lib/providers/gravatar.rb
41
+ - lib/providers/highrise.rb
42
+ - lib/providers/twitter.rb
43
+ - test/providers/test_facebook.rb
44
+ - test/providers/test_flickr.rb
45
+ - test/providers/test_gravatar.rb
46
+ - test/providers/test_highrise.rb
47
+ - test/providers/test_twitter.rb
48
+ - test/test_faces.rb
49
+ - test/test_helper.rb
50
+ has_rdoc: true
51
+ homepage: http://github.com/nickpellant/faces
52
+ licenses: []
53
+
54
+ post_install_message:
55
+ rdoc_options:
56
+ - --charset=UTF-8
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ segments:
71
+ - 0
72
+ version: "0"
73
+ requirements: []
74
+
75
+ rubyforge_project:
76
+ rubygems_version: 1.3.6
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: Faces manages external and internal avatar sources in one unified format.
80
+ test_files:
81
+ - test/providers/test_facebook.rb
82
+ - test/providers/test_flickr.rb
83
+ - test/providers/test_gravatar.rb
84
+ - test/providers/test_highrise.rb
85
+ - test/providers/test_twitter.rb
86
+ - test/test_faces.rb
87
+ - test/test_helper.rb