spacer 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ == 0.5.0 / 2008-02-09
2
+
3
+ * Initial release
4
+ * Birthday!
data/MIT-LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2008 Shane Vitarana <shanev@gmail.com>, CrimsonJet LLC
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
data/Manifest.txt ADDED
@@ -0,0 +1,34 @@
1
+ History.txt
2
+ MIT-LICENSE
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ bin/spacer
7
+ lib/spacer.rb
8
+ lib/spacer/auth.rb
9
+ lib/spacer/client.rb
10
+ lib/spacer/model.rb
11
+ lib/spacer/models/album.rb
12
+ lib/spacer/models/details.rb
13
+ lib/spacer/models/group.rb
14
+ lib/spacer/models/interest.rb
15
+ lib/spacer/models/mood.rb
16
+ lib/spacer/models/photo.rb
17
+ lib/spacer/models/profile.rb
18
+ lib/spacer/models/status.rb
19
+ lib/spacer/models/user.rb
20
+ lib/spacer/models/video.rb
21
+ tasks/annotations.rake
22
+ tasks/doc.rake
23
+ tasks/gem.rake
24
+ tasks/manifest.rake
25
+ tasks/post_load.rake
26
+ tasks/rubyforge.rake
27
+ tasks/setup.rb
28
+ tasks/spec.rake
29
+ tasks/svn.rake
30
+ tasks/test.rake
31
+ test/test_client.rb
32
+ test/test_helper.rb
33
+ test/test_spacer.rb
34
+ test/test_user.rb
data/README.txt ADDED
@@ -0,0 +1,54 @@
1
+ spacer
2
+ by Shane Vitarana
3
+ http://shanesbrain.net
4
+
5
+ == DESCRIPTION:
6
+
7
+ Ruby API for the MySpace Platform REST API
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * Implements v1.0 of the MySpace Platform REST API
12
+ * Uses JSON for minimal transport footprint
13
+
14
+ == SYNOPSIS:
15
+
16
+ @myspace = Spacer::Client.new(api_key, secret_key)
17
+ user = @myspace.user('3454354')
18
+ puts user.interests.music
19
+ puts user.photos.first.caption
20
+
21
+ == REQUIREMENTS:
22
+
23
+ * OAuth
24
+ * ActiveSupport
25
+ * Mocha (for testing)
26
+
27
+ == INSTALL:
28
+
29
+ * sudo gem install spacer
30
+
31
+ == LICENSE:
32
+
33
+ (The MIT License)
34
+
35
+ Copyright (c) 2008 Shane Vitarana <shanev@gmail.com>, CrimsonJet LLC
36
+
37
+ Permission is hereby granted, free of charge, to any person obtaining
38
+ a copy of this software and associated documentation files (the
39
+ 'Software'), to deal in the Software without restriction, including
40
+ without limitation the rights to use, copy, modify, merge, publish,
41
+ distribute, sublicense, and/or sell copies of the Software, and to
42
+ permit persons to whom the Software is furnished to do so, subject to
43
+ the following conditions:
44
+
45
+ The above copyright notice and this permission notice shall be
46
+ included in all copies or substantial portions of the Software.
47
+
48
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
49
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
50
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
51
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
52
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
53
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
54
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ # Look in the tasks/setup.rb file for the various options that can be
2
+ # configured in this Rakefile. The .rake files in the tasks directory
3
+ # are where the options are used.
4
+
5
+ load 'tasks/setup.rb'
6
+
7
+ ensure_in_path 'lib'
8
+ require 'spacer'
9
+
10
+ task :default => 'test:run'
11
+
12
+ PROJ.name = 'spacer'
13
+ PROJ.authors = 'Shane Vitarana'
14
+ PROJ.email = 'shanev@gmail.com'
15
+ PROJ.url = 'http://shanesbrain.net'
16
+ PROJ.rubyforge_name = 'spacer'
17
+
18
+ PROJ.spec_opts << '--color'
19
+
20
+ # EOF
data/bin/spacer ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(
4
+ File.join(File.dirname(__FILE__), '..', 'lib', 'spacer'))
5
+
6
+ # Put your code here
7
+
8
+ # EOF
data/lib/spacer.rb ADDED
@@ -0,0 +1,63 @@
1
+ # $Id$
2
+
3
+ # Equivalent to a header guard in C/C++
4
+ # Used to prevent the class/module from being loaded more than once
5
+ unless defined? Spacer
6
+
7
+ require 'rubygems'
8
+ require 'oauth/consumer'
9
+ require 'activesupport'
10
+ require 'spacer/model'
11
+
12
+ module Spacer
13
+
14
+ # :stopdoc:
15
+ VERSION = '0.5.0'
16
+ LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
17
+ PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
18
+ # :startdoc:
19
+
20
+ # Returns the version string for the library.
21
+ #
22
+ def self.version
23
+ VERSION
24
+ end
25
+
26
+ # Returns the library path for the module. If any arguments are given,
27
+ # they will be joined to the end of the libray path using
28
+ # <tt>File.join</tt>.
29
+ #
30
+ def self.libpath( *args )
31
+ args.empty? ? LIBPATH : ::File.join(LIBPATH, *args)
32
+ end
33
+
34
+ # Returns the lpath for the module. If any arguments are given,
35
+ # they will be joined to the end of the path using
36
+ # <tt>File.join</tt>.
37
+ #
38
+ def self.path( *args )
39
+ args.empty? ? PATH : ::File.join(PATH, *args)
40
+ end
41
+
42
+ # Utility method used to rquire all files ending in .rb that lie in the
43
+ # directory below this file that has the same name as the filename passed
44
+ # in. Optionally, a specific _directory_ name can be passed in such that
45
+ # the _filename_ does not have to be equivalent to the directory.
46
+ #
47
+ def self.require_all_libs_relative_to( fname, dir = nil )
48
+ dir ||= ::File.basename(fname, '.*')
49
+ search_me = ::File.expand_path(
50
+ ::File.join(::File.dirname(fname), dir, '**', '*.rb'))
51
+
52
+ Dir.glob(search_me).sort.each do |rb|
53
+ require rb
54
+ end
55
+ end
56
+
57
+ end # module Spacer
58
+
59
+ Spacer.require_all_libs_relative_to __FILE__
60
+
61
+ end # unless defined?
62
+
63
+ # EOF
@@ -0,0 +1,23 @@
1
+ module Spacer
2
+
3
+ class Authentication
4
+ def initialize(api_key, secret_key)
5
+ @oauth_consumer = OAuth::Consumer.new(CGI.escape(api_key), secret_key)
6
+ end
7
+
8
+ def process_request(http, request)
9
+ request.oauth!(http, @oauth_consumer, nil, { :scheme => :query_string, :nonce => nonce, :timestamp => timestamp })
10
+ request
11
+ end
12
+
13
+ private
14
+ def nonce
15
+ rand(2**128).to_s
16
+ end
17
+
18
+ def timestamp
19
+ Time.new.to_i.to_s
20
+ end
21
+ end
22
+
23
+ end
@@ -0,0 +1,141 @@
1
+ module Spacer
2
+ class Client
3
+
4
+ SERVER = 'api.msappspace.com'
5
+ VERSION = 'v1'
6
+ FORMAT = :json
7
+ LOG_LEVEL = Logger::INFO
8
+
9
+ def initialize(api_key, secret_key, logger=nil)
10
+ @auth = Authentication.new(api_key, secret_key)
11
+
12
+ if logger
13
+ @log = logger
14
+ else
15
+ @log = Logger.new(STDOUT)
16
+ @log.level = LOG_LEVEL
17
+ end
18
+ end
19
+
20
+ def user(user_id)
21
+ response = do_request "users/#{user_id}"
22
+ @user = User.from_hash_with_client(response, self)
23
+ end
24
+
25
+ def profile(user_id)
26
+ response = do_request "users/#{user_id}/profile"
27
+ @profile = Profile.from_hash(response)
28
+ end
29
+
30
+ def friends(user_id, page=nil, page_size=nil, list=nil)
31
+ response = do_request "users/#{user_id}/friends.#{FORMAT.to_s}?page=#{page}&page_size=#{page_size}&list=#{list}"
32
+ @friends = response['friends'].map do |friend|
33
+ User.from_hash_with_client(friend, self)
34
+ end
35
+ end
36
+
37
+ def albums(user_id)
38
+ response = do_request "users/#{user_id}/albums"
39
+ @albums = response['albums'].map do |album|
40
+ Album.from_hash(album)
41
+ end
42
+ end
43
+
44
+ def album(user_id, album_id)
45
+ response = do_request "users/#{user_id}/albums/#{album_id}"
46
+ @album = Album.from_hash(response)
47
+ end
48
+
49
+ def photos_for_album(user_id, album_id)
50
+ response = do_request "users/#{user_id}/albums/#{album_id}/photos"
51
+ @photos = response['photos'].map do |photo|
52
+ Photo.from_hash(photo)
53
+ end
54
+ end
55
+
56
+ def photos(user_id)
57
+ response = do_request "users/#{user_id}/photos"
58
+ @photos = response['photos'].map do |photo|
59
+ Photo.from_hash(photo)
60
+ end
61
+ end
62
+
63
+ def interests(user_id)
64
+ response = do_request "users/#{user_id}/interests"
65
+ @interests = Interest.from_hash(response)
66
+ end
67
+
68
+ def details(user_id)
69
+ response = do_request "users/#{user_id}/details"
70
+ @details = Details.from_hash(response)
71
+ end
72
+
73
+ def videos(user_id)
74
+ response = do_request "users/#{user_id}/videos"
75
+ @videos = response['videos'].map do |video|
76
+ Video.from_hash(video)
77
+ end
78
+ end
79
+
80
+ def video(user_id, video_id)
81
+ response = do_request "users/#{user_id}/videos/#{video_id}"
82
+ @video = Video.from_hash(response)
83
+ end
84
+
85
+ def photo(user_id, photo_id)
86
+ response = do_request "users/#{user_id}/photos/#{photo_id}"
87
+ @photo = Photo.from_hash(response)
88
+ end
89
+
90
+ def status(user_id)
91
+ response = do_request "users/#{user_id}/status"
92
+ @status = Status.from_hash(response)
93
+ end
94
+
95
+ def mood(user_id)
96
+ response = do_request "users/#{user_id}/mood"
97
+ @mood = Mood.from_hash(response)
98
+ end
99
+
100
+ def friendship?(user_id, friend_ids)
101
+ multiple_friends = friend_ids.is_a?(Array)
102
+
103
+ friend_ids = friend_ids.join(';') if multiple_friends
104
+ response = do_request "users/#{user_id}/friends/#{friend_ids}"
105
+
106
+ if multiple_friends
107
+ @friendships = response['friendship'].map do |friendship|
108
+ friendship['areFriends']
109
+ end
110
+ else
111
+ response['friendship'].first['areFriends']
112
+ end
113
+ end
114
+
115
+ def groups(user_id)
116
+ response = do_request "users/#{user_id}/groups"
117
+ @groups = response['Groups'].map do |group|
118
+ Group.from_hash(group)
119
+ end
120
+ end
121
+
122
+ private
123
+ def do_request(query)
124
+ request_uri = request_uri(query)
125
+
126
+ http = Net::HTTP.new(request_uri.host, request_uri.port)
127
+ request = Net::HTTP::Get.new(request_uri.path)
128
+ request = @auth.process_request(http, request)
129
+ @log.debug "REQUEST PATH: #{request.path}"
130
+
131
+ response = http.request(request)
132
+ @log.debug "RESPONSE BODY: #{response.body}\n"
133
+
134
+ ActiveSupport::JSON.decode(response.body)
135
+ end
136
+
137
+ def request_uri(query)
138
+ URI.parse("http://#{SERVER}/#{VERSION}/#{query}.#{FORMAT.to_s}")
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,124 @@
1
+ ## Graciously stolen from Facebooker
2
+ #
3
+ # Copyright (c) 2007 Chad Fowler <chad@infoether.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ # this software and associated documentation files (the "Software"), to deal in the
7
+ # Software without restriction, including without limitation the rights to use,
8
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
9
+ # Software, and to permit persons to whom the Software is furnished to do so,
10
+ # subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19
+ # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ module Spacer
23
+ ##
24
+ # helper methods primarily supporting the management of Ruby objects which are populatable via Hashes.
25
+ # Since most Facebook API calls accept and return hashes of data (as XML), the Model module allows us to
26
+ # directly populate a model's attributes given a Hash with matching key names.
27
+ module Model
28
+ class UnboundSessionException < Exception; end
29
+ def self.included(includer)
30
+ includer.extend ClassMethods
31
+ end
32
+ module ClassMethods
33
+ ##
34
+ # Instantiate a new instance of the class into which we are included and populate that instance's
35
+ # attributes given the provided Hash. Key names in the Hash should map to attribute names on the model.
36
+ def from_hash(hash)
37
+ instance = new(hash)
38
+ yield instance if block_given?
39
+ instance
40
+ end
41
+
42
+ ##
43
+ # Create a standard attr_writer and a populating_attr_reader
44
+ def populating_attr_accessor(*symbols)
45
+ attr_writer *symbols
46
+ populating_attr_reader *symbols
47
+ end
48
+
49
+ ##
50
+ # Create a reader that will attempt to populate the model if it has not already been populated
51
+ def populating_attr_reader(*symbols)
52
+ symbols.each do |symbol|
53
+ define_method(symbol) do
54
+ populate unless populated?
55
+ instance_variable_get("@#{symbol}")
56
+ end
57
+ end
58
+ end
59
+
60
+ def populating_hash_settable_accessor(symbol, klass)
61
+ populating_attr_reader symbol
62
+ hash_settable_writer(symbol, klass)
63
+ end
64
+
65
+ def populating_hash_settable_list_accessor(symbol, klass)
66
+ populating_attr_reader symbol
67
+ hash_settable_list_writer(symbol, klass)
68
+ end
69
+
70
+ #
71
+ # Declares an attribute named ::symbol:: which can be set with either an instance of ::klass::
72
+ # or a Hash which will be used to populate a new instance of ::klass::.
73
+ def hash_settable_accessor(symbol, klass)
74
+ attr_reader symbol
75
+ hash_settable_writer(symbol, klass)
76
+ end
77
+
78
+ def hash_settable_writer(symbol, klass)
79
+ define_method("#{symbol}=") do |value|
80
+ instance_variable_set("@#{symbol}", value.kind_of?(Hash) ? klass.from_hash(value) : value)
81
+ end
82
+ end
83
+
84
+ #
85
+ # Declares an attribute named ::symbol:: which can be set with either a list of instances of ::klass::
86
+ # or a list of Hashes which will be used to populate a new instance of ::klass::.
87
+ def hash_settable_list_accessor(symbol, klass)
88
+ attr_reader symbol
89
+ hash_settable_list_writer(symbol, klass)
90
+ end
91
+
92
+ def hash_settable_list_writer(symbol, klass)
93
+ define_method("#{symbol}=") do |list|
94
+ instance_variable_set("@#{symbol}", list.map do |item|
95
+ item.kind_of?(Hash) ? klass.from_hash(item) : item
96
+ end)
97
+ end
98
+ end
99
+ end
100
+
101
+ def initialize(hash = {})
102
+ populate_from_hash!(hash)
103
+ end
104
+
105
+ def populate
106
+ raise NotImplementedError, "#{self.class} included me and should have overriden me"
107
+ end
108
+
109
+ def populated?
110
+ !@populated.nil?
111
+ end
112
+
113
+ ##
114
+ # Set model's attributes via Hash. Keys should map directly to the model's attribute names.
115
+ def populate_from_hash!(hash)
116
+ unless hash.empty?
117
+ hash.each do |key, value|
118
+ self.__send__("#{key}=", value)
119
+ end
120
+ @populated = true
121
+ end
122
+ end
123
+ end
124
+ end