giggly 0.1.0

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.
@@ -0,0 +1,23 @@
1
+ = Giggly
2
+
3
+ Giggly is an attempt to create a gem for accessing Gigya Socialize
4
+ (http://www.gigya.com/site/partners/wfsocapi.aspx) via idiomatic ruby.
5
+
6
+ Consult the rdoc for detailed information.
7
+
8
+ == Example
9
+
10
+ For examples of usage, visit http://giggly.inheretic.com
11
+
12
+ == Authors
13
+
14
+ * Ben Vandgrift (http://neovore.com)
15
+ * Adam Hunter (http://adamhunter.me)
16
+
17
+ == Copyright
18
+
19
+ Copyright (c) 2009
20
+
21
+ == Credits
22
+
23
+ Sponsored by FlowMingle.com and Charlotte.com
@@ -0,0 +1,88 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'fileutils'
4
+
5
+ begin
6
+ require 'jeweler'
7
+ Jeweler::Tasks.new do |gem|
8
+ gem.name = "giggly"
9
+ gem.summary = "wrapper for the gigya rest and javascript apis"
10
+ gem.description = "breaks the gigya web api down into idiomatic ruby for your coding pleasure."
11
+ gem.email = "somethingfamiliar@gmail.com"
12
+ gem.homepage = "http://github.com/sfamiliar/giggly"
13
+ gem.authors = ["Ben Vandgrift", "Adam Hunter"]
14
+ gem.files = FileList["[A-Z]*", "{examples,lib,test,javascripts}/**/*"]
15
+ #gem.rubyforge_project = "giggly"
16
+
17
+ gem.add_dependency('httparty', '0.4.5')
18
+
19
+ gem.add_development_dependency('thoughtbot-shoulda', '>= 2.10.1')
20
+ gem.add_development_dependency('jnunemaker-matchy', '0.4.0')
21
+ gem.add_development_dependency('mocha', '0.9.4')
22
+ gem.add_development_dependency('fakeweb', '>= 1.2.5')
23
+ gem.add_development_dependency('redgreen', '>= 1.0.0')
24
+ end
25
+
26
+ Jeweler::RubyforgeTasks.new do |rubyforge|
27
+ rubyforge.doc_task = "rdoc"
28
+ end
29
+ rescue LoadError
30
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
31
+ end
32
+
33
+ require 'rake/testtask'
34
+ Rake::TestTask.new(:test) do |test|
35
+ test.libs << 'lib' << 'test'
36
+ test.pattern = 'test/**/*_test.rb'
37
+ test.verbose = false
38
+ end
39
+
40
+ begin
41
+ require 'rcov/rcovtask'
42
+ Rcov::RcovTask.new do |test|
43
+ test.libs << 'test'
44
+ test.pattern = 'test/**/*_test.rb'
45
+ test.verbose = true
46
+ end
47
+ rescue LoadError
48
+ task :rcov do
49
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
50
+ end
51
+ end
52
+
53
+
54
+ task :default => :test
55
+
56
+ require 'rake/rdoctask'
57
+ Rake::RDocTask.new do |rdoc|
58
+ if File.exist?('VERSION.yml')
59
+ config = YAML.load(File.read('VERSION.yml'))
60
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
61
+ else
62
+ version = ""
63
+ end
64
+
65
+ rdoc.rdoc_dir = 'rdoc'
66
+ rdoc.title = "giggly #{version}"
67
+ rdoc.rdoc_files.include('README*')
68
+ rdoc.rdoc_files.include('lib/**/*.rb')
69
+ end
70
+
71
+ def copy_js(source, destination)
72
+ destination ||= '.'
73
+ FileUtils.cp File.join(File.dirname(__FILE__), 'javascripts', source), destination
74
+ puts "wrote #{source} to #{destination}"
75
+ end
76
+
77
+ namespace :giggly do
78
+ desc "writes out the giggly-socialize.js api wrapper in the given directory. ex) rake giggly:js IN=path/to/write (IN defaults to the current directory)"
79
+ task :js do
80
+ copy_js 'giggly-socialize.js', ENV['IN']
81
+ end
82
+
83
+ desc "writes out the minified version of giggly-socialize"
84
+ task :"js:min" do
85
+ copy_js 'giggly-socialize-min.js', ENV['IN']
86
+ end
87
+ end
88
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,8 @@
1
+ /*
2
+ * Wrapper for Gigya's Javascript Socialize API
3
+ * http://
4
+ * http://gigya.com
5
+ *
6
+ * Dual licensed under the MIT and GPL licenses.
7
+ */
8
+ eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('B=1(h){0.4=h;0.q=1(a,b,c,d,e){2 f={\'m\':a,\'6\':i(b,c),\'7\':e,\'r\':d};5 8.9.j.q(0.4,f)};0.n=1(a,b,c,d,e,f){2 g={\'m\':a,\'7\':f,\'r\':e};3(o!=b&&o!=c){p.C(\'D E F G H I J K 3 L M N s.\')}3(o==b){g[\'6\']=i(c,d)}l{g[\'s\']=b}5 8.9.j.n(0.4,g)};0.t=1(a,b,c){2 d={\'7\':c,\'6\':i(a,b)};5 8.9.j.t(0.4,d)};0.u=1(a,b,c){2 d={\'7\':c,\'6\':i(a,b)};5 8.9.j.u(0.4,d)};0.v=1(a,b,c){2 d={\'7\':c,\'6\':i(a,b)};5 8.9.j.v(0.4,d)};0.w=1(a,b,c,d,e,f){2 g={\'7\':f,\'6\':i(d,e)};3(\'1\'==k a){g[\'O\']=a}3(\'1\'==k b){g[\'P\']=b}3(\'1\'==k c){g[\'Q\']=c}5 8.9.j.w(0.4,g)};0.x=1(a,b,c,d){2 e={\'m\':a,\'7\':d,\'6\':i(b,c)};5 8.9.j.x(0.4,e)};0.y=1(a,b,c,d){3(\'R\'!=k a){a=\'n,S,T,U,z\'}2 e={\'6\':i(b,c),\'7\':d,\'V\':a};5 8.9.j.y(0.4,e)};2 i=1(b,c){2 d=1(a){3(\'W\'==a.z){3(\'1\'==k b){b(a)}l{p.X(a)}}l{3(\'1\'==k c){c(a)}l{p.A("Y A Z 10! 11 12: ("+a.13+") 14 15: "+a.16)}}};5 d}}',62,69,'this|function|var|if|config|return|callback|context|gigya|services||||||||||socialize|typeof|else|provider|login|null|console|connect|useFacebookConnect|redirect|isLoggedIn|logout|getUserInfo|addEventHandlers|disconnect|getAvailableProviders|status|error|Giggly|warn|The|onSuccess|and|onFailure|params|will|be|ignored|passed|in|with|onLogin|onConnect|onDisconnect|string|notifications|actions|friends|requiredCapabilities|OK|log|An|has|occurred|Error|details|statusMessage|In|method|operation'.split('|'),0,{}))
@@ -0,0 +1,109 @@
1
+
2
+ Giggly = function(gigyaConfig) {
3
+
4
+ this.config = gigyaConfig;
5
+
6
+ this.connect = function(provider, onSuccess, onFailure, useFacebookConnect, context) {
7
+ var params = {
8
+ 'provider': provider,
9
+ 'callback': _onSuccessOrFailure(onSuccess, onFailure),
10
+ 'context' : context,
11
+ 'useFacebookConnect' : useFacebookConnect
12
+ };
13
+ return gigya.services.socialize.connect(this.config, params);
14
+ };
15
+
16
+ this.login = function(provider, redirect, onSuccess, onFailure, useFacebookConnect, context) {
17
+ var params = {
18
+ 'provider': provider,
19
+ 'context' : context,
20
+ 'useFacebookConnect' : useFacebookConnect
21
+ };
22
+ if (null != redirect && null != onSuccess) {
23
+ console.warn('The onSuccess and onFailure params will be ignored if passed in with redirect.');
24
+ }
25
+ if (null == redirect) {
26
+ params['callback'] = _onSuccessOrFailure(onSuccess, onFailure);
27
+ } else {
28
+ params['redirect'] = redirect;
29
+ }
30
+ return gigya.services.socialize.login(this.config, params);
31
+ };
32
+
33
+ this.isLoggedIn = function(onSuccess, onFailure, context) {
34
+ var params = {
35
+ 'context' : context,
36
+ 'callback': _onSuccessOrFailure(onSuccess, onFailure)
37
+ };
38
+ return gigya.services.socialize.isLoggedIn(this.config, params);
39
+ };
40
+
41
+ this.logout = function(onSuccess, onFailure, context) {
42
+ var params = {
43
+ 'context' : context,
44
+ 'callback': _onSuccessOrFailure(onSuccess, onFailure)
45
+ };
46
+ return gigya.services.socialize.logout(this.config, params);
47
+ };
48
+
49
+ this.getUserInfo = function(onSuccess, onFailure, context) {
50
+ var params = {
51
+ 'context' : context,
52
+ 'callback': _onSuccessOrFailure(onSuccess, onFailure)
53
+ };
54
+ return gigya.services.socialize.getUserInfo(this.config, params);
55
+ };
56
+
57
+ this.addEventHandlers = function(onLogin, onConnect, onDisconnect, onSuccess, onFailure, context) {
58
+ var params = {
59
+ 'context' : context,
60
+ 'callback': _onSuccessOrFailure(onSuccess, onFailure)
61
+ };
62
+ if ('function' == typeof onLogin) { params['onLogin'] = onLogin; }
63
+ if ('function' == typeof onConnect) { params['onConnect'] = onConnect; }
64
+ if ('function' == typeof onDisconnect) { params['onDisconnect'] = onDisconnect; }
65
+ return gigya.services.socialize.addEventHandlers(this.config, params);
66
+ };
67
+
68
+ this.disconnect = function(provider, onSuccess, onFailure, context) {
69
+ var params = {
70
+ 'provider': provider,
71
+ 'context' : context,
72
+ 'callback': _onSuccessOrFailure(onSuccess, onFailure)
73
+ };
74
+ return gigya.services.socialize.disconnect(this.config, params);
75
+ };
76
+
77
+ // currently supported capabilities are: login, notifications, actions, friends, status
78
+ this.getAvailableProviders = function(requiredCapabilities, onSuccess, onFailure, context) {
79
+ if ('string' != typeof requiredCapabilities) {
80
+ requiredCapabilities = 'login,notifications,actions,friends,status';
81
+ }
82
+ var params = {
83
+ 'callback': _onSuccessOrFailure(onSuccess, onFailure),
84
+ 'context' : context,
85
+ 'requiredCapabilities' : requiredCapabilities
86
+ };
87
+ return gigya.services.socialize.getAvailableProviders(this.config, params);
88
+ };
89
+
90
+ var _onSuccessOrFailure = function(success, failure) {
91
+ var onSuccessOrFailure = function(response) {
92
+ if ('OK' == response.status) {
93
+ if ('function' == typeof success) {
94
+ success(response);
95
+ } else {
96
+ console.log(response);
97
+ }
98
+ } else {
99
+ if ('function' == typeof failure) {
100
+ failure(response);
101
+ } else {
102
+ console.error("An error has occurred! Error details: (" + response.statusMessage + ") In method: " + response.operation);
103
+ }
104
+ }
105
+ };
106
+ return onSuccessOrFailure;
107
+ };
108
+
109
+ }
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+
3
+ gem 'httparty', '0.4.5'
4
+ require 'httparty'
5
+
6
+ # breaks the gigya web api down into idiomatic ruby for your coding pleasure.
7
+ module Giggly
8
+
9
+ end
10
+
11
+ directory = File.expand_path(File.dirname(__FILE__))
12
+
13
+ require File.join(directory, 'giggly', 'rest')
14
+ require File.join(directory, 'giggly', 'javascript')
15
+ require File.join(directory, 'giggly', 'user')
16
+ require File.join(directory, 'giggly', 'friend')
17
+ require File.join(directory, 'giggly', 'session_info')
18
+
@@ -0,0 +1,4 @@
1
+ module Giggly
2
+ class Friend < Giggly::User
3
+ end
4
+ end
@@ -0,0 +1,10 @@
1
+ module Giggly
2
+ module Javascript
3
+
4
+ end
5
+ end
6
+
7
+ directory = File.expand_path(File.dirname(__FILE__))
8
+
9
+ require File.join(directory, 'javascript', 'helper')
10
+ require File.join(directory, 'javascript', 'socialize')
@@ -0,0 +1,45 @@
1
+ module Giggly
2
+ module Javascript
3
+ module Helper
4
+
5
+ # The Javascript helper should be totally generic to the api that is being used
6
+ # So that if there is a future api it can be wrapped in a class and include this
7
+
8
+ def include_gigya_api(service)
9
+ '<script type="text/javascript" src="http://cdn.gigya.com/JS/gigya.js?services=' + service.to_s + '"></script>'
10
+ end
11
+
12
+ def javascript(&block)
13
+ out = '<script type="text/javascript">' + "\n"
14
+ out += yield.to_s
15
+ out += "\n" + '</script>'
16
+ out
17
+ end
18
+
19
+ def to_var(name, object, scope_to_window = false)
20
+ "#{scope_to_window ? '' : 'var '}#{name.to_s} = #{javascriptify_object object};"
21
+ end
22
+
23
+ # borrowed mainly from the ym4r_gm plugin
24
+ def javascriptify_object(object)
25
+ if object.is_a? String
26
+ "'#{escape_javascript object}'"
27
+ elsif object.is_a? Array
28
+ '[' + object.collect{ |o| javascriptify_variable(o) }.join(', ') + ']'
29
+ elsif object.is_a? Hash
30
+ '{' + object.to_a.collect{ |o| "#{o[0].to_s} : #{javascriptify_object(o[1])}" }.join(', ') + '}'
31
+ elsif object.nil?
32
+ 'undefined'
33
+ else
34
+ object.to_s
35
+ end
36
+ end
37
+
38
+ # from rails
39
+ def escape_javascript(javascript)
40
+ javascript.gsub(/\r\n|\n|\r/, "\\n").gsub("\"") { |m| "\\#{m}" }
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,46 @@
1
+ module Giggly
2
+ module Javascript
3
+ class Socialize
4
+ include Giggly::Javascript::Helper
5
+
6
+ attr_accessor :api_key, :enabled_providers, :disabled_providers, :config
7
+
8
+ def initialize(config)
9
+ @api_key = config[:api_key]
10
+ @enabled_providers = array_to_string(config[:enabled_providers])
11
+ @disabled_providers = array_to_string(config[:disabled_providers])
12
+
13
+ @config = to_config
14
+ end
15
+
16
+ def to_config
17
+ {
18
+ 'APIKey' => @api_key,
19
+ 'enabledProviders' => @enabled_providers,
20
+ 'disabledProviders' => @disabled_providers
21
+ }.reject { |k,v| v.nil? }
22
+ end
23
+
24
+ # Socialize specific JS methods
25
+
26
+ def config_to_js(config_var_name = :gigyaConfig)
27
+ to_var(config_var_name, to_config)
28
+ end
29
+
30
+ def include_gigya_socialize(js_path = '/javascripts', min = true)
31
+ include_gigya_api(:socialize) + "\n<script type=\"text/javascript\" src=\"#{js_path}/giggly-socialize#{'-min' if min}.js\"></script>"
32
+ end
33
+
34
+ protected
35
+
36
+ def array_to_string(array)
37
+ if array.is_a? String
38
+ array
39
+ elsif array.is_a? Array
40
+ array.join(',')
41
+ end
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,32 @@
1
+ require 'digest'
2
+ require 'hmac-sha1'
3
+ require 'base64'
4
+ require 'cgi'
5
+
6
+ module Giggly
7
+ module Rest
8
+
9
+ class SocializeError < StandardError
10
+ attr_reader :error_code
11
+
12
+ def initialize(error_data)
13
+ @error_code = error_data["errorCode"]
14
+ super(error_data["errorMessage"])
15
+ end
16
+ end
17
+
18
+ class BadRequest < SocializeError; end
19
+ class Unauthorized < SocializeError; end
20
+ class Forbidden < SocializeError; end
21
+ class NotFound < SocializeError; end
22
+ class RequestEntityTooLarge < SocializeError; end
23
+ class InternalServerError < SocializeError; end
24
+ class NotImplemented < SocializeError; end
25
+
26
+ end
27
+ end
28
+
29
+ directory = File.expand_path(File.dirname(__FILE__))
30
+
31
+ require File.join(directory, 'rest', 'request')
32
+ require File.join(directory, 'rest', 'socialize')
@@ -0,0 +1,85 @@
1
+ module Giggly
2
+ module Rest
3
+ class Request
4
+ include HTTParty
5
+ attr_accessor :api_key, :secret_key, :uid
6
+ format :xml
7
+
8
+ # Accepts a hash of connection parameters that will be used to authenticate requests with gigya
9
+ # and specify the user that the request is specific to. The keys for the has are all symbols.
10
+ # The connection parameter hash requires :api_key, :secret_key, and :uid
11
+ # These are the same parameters that can be passed to the constructor for +Giggly::Rest::Socialize+
12
+ # example:
13
+ # @connection = Giggly::Rest::Request.new(
14
+ # :api_key => 'api key provided from Gigya',
15
+ # :secret_key => 'secret key provided from Gigya',
16
+ # :user_id => 'the Gigya User ID',
17
+ # )
18
+ def initialize(conn_params)
19
+ @api_key = conn_params[:api_key]
20
+ @secret_key = conn_params[:secret_key]
21
+ @uid = conn_params[:user_id]
22
+ @gigya_secret = Base64.decode64(@secret_key)
23
+ end
24
+
25
+ # Wraps around HTTParty's post method to make API calls.
26
+ # Responsible for raising errors if they are returned from the API.
27
+ # Returns response data from the post request.
28
+ def post(url, params = {})
29
+ response = self.class.post(url, :query => sign('POST', url, params))
30
+ response_key, response_data = response.shift
31
+ raise_errors(response_data)
32
+ response_data
33
+ end
34
+
35
+ def sign(http_method, api_url, params)
36
+ params.merge! "apiKey" => @api_key, "uid" => @uid
37
+ params.merge "sig" => signature(api_url, http_method, params)
38
+ end
39
+
40
+ def signature(http_method, api_url, params)
41
+ timestamp = Time.now.to_i.to_s
42
+ params.merge!("nonce" => "#{@uid}#{timestamp}", "timestamp" => timestamp) ####
43
+ base_string = build_base_string(http_method, api_url, params)
44
+ hmacsha1 = HMAC::SHA1.digest(@gigya_secret, base_string)
45
+ sig = Base64.encode64(hmacsha1).chomp.to_s.gsub(/\n/,'')
46
+ end
47
+
48
+ private
49
+
50
+ # what is this supposed to do? or when is it supposed to be used?
51
+ def validate_signature(api_url, params, sig)
52
+ sig === signature(api_url, params)
53
+ end
54
+
55
+ def params_to_string(params)
56
+ params.sort {|a,b| a[0].to_s <=> b[0].to_s}.collect {|a| "#{a[0]}=#{CGI.escape a[1].to_s}"}.join('&').gsub('+', '%20')
57
+ end
58
+
59
+ def build_base_string(http_method, api_url, params)
60
+ [http_method, api_url, params_to_string(params)].collect! {|a| CGI.escape a}.join('&')
61
+ end
62
+
63
+ def raise_errors(data)
64
+ return if '200' == data["statusCode"]
65
+ case data["statusCode"].to_i
66
+ when 400
67
+ raise Giggly::Rest::BadRequest.new(data)
68
+ when 401
69
+ raise Giggly::Rest::Unauthorized.new(data)
70
+ when 403
71
+ raise Giggly::Rest::Forbidden.new(data)
72
+ when 404
73
+ raise Giggly::Rest::NotFound.new(data)
74
+ when 413
75
+ raise Giggly::Rest::RequestEntityTooLarge.new(data)
76
+ when 500
77
+ raise Giggly::Rest::InternalServerError.new(data)
78
+ when 503
79
+ raise Giggly::Rest::NotImplemented.new(data)
80
+ end
81
+ end
82
+
83
+ end
84
+ end
85
+ end