fb_joy 0.1.2
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.
- data/Gemfile +13 -0
- data/Gemfile.lock +38 -0
- data/LICENSE +20 -0
- data/README.md +78 -0
- data/Rakefile +39 -0
- data/VERSION +1 -0
- data/fb_joy.gemspec +88 -0
- data/lib/fb_joy.rb +12 -0
- data/lib/joey/action.rb +16 -0
- data/lib/joey/affiliation.rb +15 -0
- data/lib/joey/album.rb +42 -0
- data/lib/joey/comment.rb +20 -0
- data/lib/joey/education.rb +20 -0
- data/lib/joey/education_history.rb +15 -0
- data/lib/joey/fetching_array.rb +26 -0
- data/lib/joey/hs_info.rb +15 -0
- data/lib/joey/image.rb +5 -0
- data/lib/joey/like.rb +13 -0
- data/lib/joey/location.rb +17 -0
- data/lib/joey/model.rb +84 -0
- data/lib/joey/page.rb +31 -0
- data/lib/joey/parser_helpers.rb +7 -0
- data/lib/joey/photo.rb +41 -0
- data/lib/joey/post.rb +67 -0
- data/lib/joey/privacy.rb +15 -0
- data/lib/joey/profile.rb +33 -0
- data/lib/joey/property.rb +15 -0
- data/lib/joey/relative.rb +15 -0
- data/lib/joey/rest_api.rb +116 -0
- data/lib/joey/status.rb +15 -0
- data/lib/joey/tag.rb +15 -0
- data/lib/joey/television.rb +15 -0
- data/lib/joey/user.rb +83 -0
- data/lib/joey/version.rb +9 -0
- data/lib/joey/video.rb +22 -0
- data/lib/joey/work.rb +20 -0
- data/lib/joey/work_history.rb +18 -0
- metadata +167 -0
data/lib/joey/hs_info.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
module Joey
|
2
|
+
class HsInfo < Model
|
3
|
+
define_properties :hs1_name, :hs2_name, :grad_year
|
4
|
+
|
5
|
+
def validate
|
6
|
+
valid = true
|
7
|
+
end
|
8
|
+
|
9
|
+
def valid?
|
10
|
+
self.validate
|
11
|
+
puts self.errors.inspect unless self.errors.empty?
|
12
|
+
self.errors.empty?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/joey/image.rb
ADDED
data/lib/joey/like.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module Joey
|
2
|
+
class Location < Model
|
3
|
+
define_properties :name, :zip, :country, :id, :state, :city
|
4
|
+
|
5
|
+
def validate
|
6
|
+
valid = true
|
7
|
+
errors << { :message => "country should be string but is #{country.inspect}" } unless country.is_a?(String)
|
8
|
+
errors << { :message => "city should be string but is #{city.inspect}" } unless city.is_a?(String)
|
9
|
+
end
|
10
|
+
|
11
|
+
def valid?
|
12
|
+
self.validate
|
13
|
+
puts self.errors.inspect unless self.errors.empty?
|
14
|
+
self.errors.empty?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/joey/model.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
module Joey
|
2
|
+
class Model < Hashie::Dash
|
3
|
+
|
4
|
+
class KoalaClientRequiredError < Exception; end
|
5
|
+
|
6
|
+
attr_accessor :client, :errors
|
7
|
+
|
8
|
+
def initialize(hash = {}, client = nil)
|
9
|
+
self.client = client
|
10
|
+
self.errors = []
|
11
|
+
|
12
|
+
super(hash || {})
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.define_properties(*args)
|
16
|
+
args.each do |arg|
|
17
|
+
property arg
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.recognize?(data)
|
22
|
+
true
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.hash_populating_accessor(method_name, *klass)
|
26
|
+
define_method "#{method_name}=" do |hash|
|
27
|
+
instance_variable_set("@#{method_name}", client.map_data(hash, klass))
|
28
|
+
end
|
29
|
+
|
30
|
+
define_method "#{method_name}" do
|
31
|
+
instance_variable_get "@#{method_name}"
|
32
|
+
end
|
33
|
+
#add_creation_method(method_name,klass)
|
34
|
+
end
|
35
|
+
|
36
|
+
# TODO: Look out for creation of nodes in the Graph
|
37
|
+
# me = koala_client.me
|
38
|
+
# me.friends_create(args)
|
39
|
+
#def self.add_creation_method(name, klass)
|
40
|
+
#define_method "#{name}_create" do |arg|
|
41
|
+
#params = arg.nil? ? {} : arg.post_params
|
42
|
+
#klass_to_send = arg.nil? ? nil : klass
|
43
|
+
#client.post("#{id}/#{name}", klass_to_send, params)
|
44
|
+
#end
|
45
|
+
#end
|
46
|
+
|
47
|
+
def self.hash_populating_association(method_name, *klass)
|
48
|
+
define_method "#{method_name}=" do |hash|
|
49
|
+
instance_variable_set("@#{method_name}", client.map_data(hash, klass))
|
50
|
+
end
|
51
|
+
|
52
|
+
define_method(method_name) do
|
53
|
+
if (ret = instance_variable_get("@#{method_name}")).nil?
|
54
|
+
ret = client.get_and_map("#{id}/#{method_name}", klass)
|
55
|
+
instance_variable_set("@#{method_name}", ret)
|
56
|
+
end
|
57
|
+
return ret
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.has_association(name, klass)
|
62
|
+
define_method(name) do
|
63
|
+
if (ret = instance_variable_get("@#{name}")).nil?
|
64
|
+
ret = client.get_and_map("#{id}/#{name}", klass)
|
65
|
+
instance_variable_set("@#{name}", ret)
|
66
|
+
end
|
67
|
+
return ret
|
68
|
+
end
|
69
|
+
|
70
|
+
#add_creation_method(name, klass)
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# Get some information of a node in the Graph.
|
75
|
+
# Joey::Post.find('19440638720_133872233324170', client, :fields => 'name,link,description,comments')
|
76
|
+
def self.find(id, client = nil, args = {})
|
77
|
+
client.get_and_map(id, self, args)
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.get_all(ids, client = nil, args = {})
|
81
|
+
client.get_all_and_map(ids, self, args)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/joey/page.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
module Joey
|
2
|
+
class Page < Profile
|
3
|
+
|
4
|
+
define_properties :id, :name, :category, :username, :category
|
5
|
+
|
6
|
+
# General
|
7
|
+
define_properties :likes, :link, :picture, :has_added_app
|
8
|
+
|
9
|
+
# Retail
|
10
|
+
define_properties :founded, :products, :mission, :company_overview
|
11
|
+
|
12
|
+
# Musicians
|
13
|
+
define_properties :record_label, :hometown, :band_members, :genre
|
14
|
+
|
15
|
+
def self.recognize?(hash)
|
16
|
+
hash.has_key?("category")
|
17
|
+
end
|
18
|
+
|
19
|
+
def validate
|
20
|
+
valid = true
|
21
|
+
errors << { :message => 'id should not be nil' } if id.nil?
|
22
|
+
errors << { :message => "name should be string but is #{name.inspect}" } unless name.is_a?(String)
|
23
|
+
end
|
24
|
+
|
25
|
+
def valid?
|
26
|
+
self.validate
|
27
|
+
puts self.errors.inspect unless self.errors.empty?
|
28
|
+
self.errors.empty?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/joey/photo.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
module Joey
|
2
|
+
class Photo < Model
|
3
|
+
define_properties :id, :name, :picture, :source, :height, :width, :link, :icon,
|
4
|
+
:created_time, :updated_time, :position
|
5
|
+
#creation_properties :message
|
6
|
+
|
7
|
+
hash_populating_accessor :from, "User","Page"
|
8
|
+
hash_populating_accessor :comments, "Comment"
|
9
|
+
hash_populating_accessor :tags, "Tag"
|
10
|
+
hash_populating_accessor :images, "Image"
|
11
|
+
#has_association :comments, "Comment"
|
12
|
+
|
13
|
+
def validate
|
14
|
+
created_time.to_time rescue errors << { :message => 'created_time is not compatible' }
|
15
|
+
updated_time.to_time rescue errors << { :message => 'updated_time is not compatible' }
|
16
|
+
errors << { :message => 'id should not be nil' } if id.nil?
|
17
|
+
errors << { :message => "name is neither string nor nil but is #{name.inspect}" } unless name.is_a?(String) || name.nil?
|
18
|
+
errors << { :message => "source is neither string nor nil but is #{source.inspect}" } unless source.is_a?(String) || source.nil?
|
19
|
+
errors << { :message => "height is neither integer nor nil but is #{height.inspect}" } unless height.is_a?(Integer) || height.nil?
|
20
|
+
errors << { :message => "icon is neither string nor nil but is #{icon.inspect}" } unless icon.is_a?(String) || icon.nil?
|
21
|
+
errors << { :message => "width is neither integer nor nil but is #{width.inspect}" } unless width.is_a?(Integer) || width.nil?
|
22
|
+
errors << { :message => "from is not a Joey::User or Joey::Page and is #{from.inspect}" } unless from.is_a?(Joey::User) || from.is_a?(Joey::Page)
|
23
|
+
|
24
|
+
errors << { :message => "comments is not an array nor nil and is #{comments.inspect}" } unless comments.is_a?(Array) || comments.nil?
|
25
|
+
if comments.is_a?(Array) && !(comments.collect(&:class).uniq - [Joey::Comment]).empty?
|
26
|
+
errors << { :message => 'comments is not an array of Joey::Comment' }
|
27
|
+
end
|
28
|
+
|
29
|
+
errors << { :message => "tags is not an array nor nil and is #{tags.inspect}" } unless tags.is_a?(Array) || tags.nil?
|
30
|
+
if tags.is_a?(Array) && !(tags.collect(&:class).uniq - [Joey::Tag]).empty?
|
31
|
+
errors << { :message => 'tags is not an array of Joey::Comment' }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def valid?
|
36
|
+
self.validate
|
37
|
+
puts self.errors.inspect unless self.errors.empty?
|
38
|
+
self.errors.empty?
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/joey/post.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
module Joey
|
2
|
+
class Post < Model
|
3
|
+
|
4
|
+
define_properties :id, :message, :picture, :link, :name, :caption,
|
5
|
+
:description, :source, :icon, :attribution,
|
6
|
+
:created_time, :updated_time, :type, :object_id, :application
|
7
|
+
|
8
|
+
#creation_properties :message, :picture, :link, :name, :description
|
9
|
+
|
10
|
+
hash_populating_accessor :actions, "Action"
|
11
|
+
hash_populating_accessor :comments, "Comment"
|
12
|
+
hash_populating_accessor :from, "User", "Page"
|
13
|
+
hash_populating_accessor :to, "User", "Page"
|
14
|
+
hash_populating_accessor :privacy, "Privacy"
|
15
|
+
hash_populating_accessor :properties, "Property"
|
16
|
+
hash_populating_accessor :likes, "Like"
|
17
|
+
|
18
|
+
def validate
|
19
|
+
created_time.to_time rescue errors << { :message => 'created_time is not compatible' }
|
20
|
+
updated_time.to_time rescue errors << { :message => 'updated_time is not compatible' }
|
21
|
+
errors << { :message => 'id should not be nil' } if id.nil?
|
22
|
+
errors << { :message => "name is neither string nor nil but is #{name.inspect}" } unless name.is_a?(String) || name.nil?
|
23
|
+
errors << { :message => "message is neither string nor nil but is #{message.inspect}" } unless message.is_a?(String) || message.nil?
|
24
|
+
errors << { :message => "likes is neither string nor nil but is #{likes.inspect}" } unless likes.is_a?(Integer) || likes.nil? || likes.is_a?(Array)
|
25
|
+
errors << { :message => "icon is neither string nor nil but is #{icon.inspect}" } unless icon.is_a?(String) || icon.nil?
|
26
|
+
errors << { :message => "attribution is neither string nor nil but is #{attribution.inspect}" } unless attribution.is_a?(String) || attribution.nil?
|
27
|
+
|
28
|
+
unless ['music', 'photo', 'video', 'status', 'link'].include?(type)
|
29
|
+
errors << { :message => "type should be one of 'music', 'video', 'status', or 'link' but is #{type}" }
|
30
|
+
end
|
31
|
+
|
32
|
+
if type == 'picture' && !picture.is_a?(String)
|
33
|
+
errors << { :message => "picture is not present for picture post and is #{picture.inspect}" }
|
34
|
+
end
|
35
|
+
|
36
|
+
if type == 'link' && !link.is_a?(String)
|
37
|
+
errors << { :message => "picture is not present for picture post and is #{picture.inspect}" }
|
38
|
+
end
|
39
|
+
|
40
|
+
errors << { :message => "from is not a Joey::User or Joey::Page and is #{from.inspect}" } unless from.is_a?(Joey::User) || from.is_a?(Joey::Page)
|
41
|
+
|
42
|
+
errors << { :message => "to is neither an array nor nil and is #{to.inspect}" } unless to.is_a?(Array) || to.nil?
|
43
|
+
if to.is_a?(Array) && !(to.collect(&:class).uniq - [Joey::User, Joey::Page]).empty?
|
44
|
+
errors << { :message => 'to is not an array of Joey::User or Joey::Page' }
|
45
|
+
end
|
46
|
+
|
47
|
+
# TODO: Explore following approach.
|
48
|
+
# errors << { :message => 'Comments is not valid' }, unless comment.nil? || (comments.collect(&:valid?).uniq - [true]).empty?
|
49
|
+
|
50
|
+
# Sometimes comments is a single Joey::Comment object
|
51
|
+
errors << { :message => "comments is not an array nor nil and is #{comments.inspect}" } unless comments.is_a?(Array) || comments.nil?
|
52
|
+
if comments.is_a?(Array) && !(comments.collect(&:class).uniq - [Joey::Comment]).empty?
|
53
|
+
errors << { :message => 'comments is not an array of Joey::Comment' }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def valid?
|
58
|
+
self.validate
|
59
|
+
puts self.errors.inspect unless self.errors.empty?
|
60
|
+
self.errors.empty?
|
61
|
+
end
|
62
|
+
|
63
|
+
#def likes_create
|
64
|
+
#client.post("#{id}/likes",nil,{})
|
65
|
+
#end
|
66
|
+
end
|
67
|
+
end
|
data/lib/joey/privacy.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
module Joey
|
2
|
+
class Privacy < Model
|
3
|
+
define_properties :value, :description, :allow, :friends, :deny
|
4
|
+
|
5
|
+
def validate
|
6
|
+
valid = true
|
7
|
+
end
|
8
|
+
|
9
|
+
def valid?
|
10
|
+
self.validate
|
11
|
+
puts self.errors.inspect unless self.errors.empty?
|
12
|
+
self.errors.empty?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/joey/profile.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'joey/model'
|
2
|
+
|
3
|
+
module Joey
|
4
|
+
class Profile < Model
|
5
|
+
define_properties :id, :name
|
6
|
+
|
7
|
+
has_association :feed, "Post"
|
8
|
+
#has_association :links, "Link"
|
9
|
+
has_association :photos, "Photo"
|
10
|
+
#has_association :groups, "Group"
|
11
|
+
has_association :albums,"Album"
|
12
|
+
has_association :videos, "Video"
|
13
|
+
#has_association :notes, "Note"
|
14
|
+
has_association :posts, "Post"
|
15
|
+
#has_association :events, "Event"
|
16
|
+
#has_association :links, "Link"
|
17
|
+
has_association :statuses, "Status"
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
name
|
21
|
+
end
|
22
|
+
|
23
|
+
def validate
|
24
|
+
valid = true
|
25
|
+
end
|
26
|
+
|
27
|
+
def valid?
|
28
|
+
self.validate
|
29
|
+
puts self.errors.inspect unless self.errors.empty?
|
30
|
+
self.errors.empty?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'joey/parser_helpers'
|
2
|
+
|
3
|
+
module Joey
|
4
|
+
module RestAPI
|
5
|
+
|
6
|
+
include Joey::ParserHelpers
|
7
|
+
|
8
|
+
class UnrecognizeableClassError < Exception; end
|
9
|
+
|
10
|
+
def self.included(base)
|
11
|
+
base.extend(ClassMethods)
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
end
|
16
|
+
|
17
|
+
def me
|
18
|
+
get_and_map('me', Joey::User)
|
19
|
+
end
|
20
|
+
|
21
|
+
def revoke_app_permission(ext_perm)
|
22
|
+
# no need to boolianize. It returns true/false.
|
23
|
+
self.rest_call("auth.revokeExtendedPermission", :perm => ext_perm.to_s)
|
24
|
+
end
|
25
|
+
|
26
|
+
# path can be some node id in the Facebook Graph e.g. 'me', 'me/feed', '1234567890/feed'.
|
27
|
+
# klass is wrapper class for that node.
|
28
|
+
def get_and_map(path, klass = nil, args = {})
|
29
|
+
data = self.get_object(path, args)
|
30
|
+
map_data(data, klass)
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_all_and_map(ids, klass = nil, args = {})
|
34
|
+
data = self.get_objects(ids, args)
|
35
|
+
map_data({ 'data' => data.values }, klass)
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_and_map_url(url, klass = nil)
|
39
|
+
# FIXME: following only returns a hash like {"id"=>"http://graph.facebook.com/100000637452380/feed"}
|
40
|
+
# try to write a method in koala which can request absolute Facebook urls. See fetching_array.rb:7.
|
41
|
+
data = self.class.get_object(url)
|
42
|
+
map_data(data,klass)
|
43
|
+
end
|
44
|
+
|
45
|
+
def map_data(data, klass = nil)
|
46
|
+
raise_error_if_necessary(data)
|
47
|
+
hash_or_array = extract_hash_or_array(data, klass)
|
48
|
+
hash_or_array = map_to_class(hash_or_array, klass) if klass
|
49
|
+
# TODO: Validate an object here.
|
50
|
+
#hash_or_array.validate and puts hash_or_array.class.inspect if hash_or_array.is_a?(Model)
|
51
|
+
hash_or_array
|
52
|
+
end
|
53
|
+
|
54
|
+
def extract_hash_or_array(hash_or_array, klass)
|
55
|
+
return nil unless hash_or_array
|
56
|
+
return hash_or_array if hash_or_array.kind_of?(Array)
|
57
|
+
return extract_fetching_array(hash_or_array, klass) if hash_or_array.has_key?("data")
|
58
|
+
return hash_or_array
|
59
|
+
end
|
60
|
+
|
61
|
+
def extract_fetching_array(hash, klass)
|
62
|
+
f = Joey::FetchingArray.new
|
63
|
+
f.concat(hash["data"])
|
64
|
+
f.client = self
|
65
|
+
f.classes = Array(klass)
|
66
|
+
if hash["paging"]
|
67
|
+
f.next_url = hash["paging"]["next"]
|
68
|
+
f.previous_url = hash["paging"]["previous"]
|
69
|
+
end
|
70
|
+
if hash["count"]
|
71
|
+
f.count = hash['count']
|
72
|
+
end
|
73
|
+
f
|
74
|
+
end
|
75
|
+
|
76
|
+
def map_to_class(hash_or_array, klass)
|
77
|
+
return nil if hash_or_array.nil?
|
78
|
+
if hash_or_array.kind_of?(Array)
|
79
|
+
hash_or_array.map! {|elmnt| create_instance(klass, elmnt)}
|
80
|
+
else
|
81
|
+
hash_or_array = create_instance(klass, hash_or_array)
|
82
|
+
end
|
83
|
+
hash_or_array
|
84
|
+
end
|
85
|
+
|
86
|
+
def create_instance(klass, data)
|
87
|
+
klass = determine_class(klass, data)
|
88
|
+
if klass.nil?
|
89
|
+
raise UnrecognizeableClassError.new("unable to recognize klass for #{klass.inspect} => #{data.inspect}")
|
90
|
+
end
|
91
|
+
klass.new(data, self)
|
92
|
+
end
|
93
|
+
|
94
|
+
def constantize_string(klass)
|
95
|
+
# FIXME: cost_get is buggy on some versions of Ruby
|
96
|
+
# klass.is_a?(String) ? Joey.const_get(klass) : klass
|
97
|
+
klass.is_a?(String) ? (klass =~ /Joey/ ? klass.constantize : ("Joey::"+ klass).constantize) : klass
|
98
|
+
end
|
99
|
+
|
100
|
+
def determine_class(klass_or_klasses, data)
|
101
|
+
klasses = Array(klass_or_klasses).map { |k| constantize_string(k)}
|
102
|
+
klasses.detect {|klass| klass.recognize?(data)} || klasses.first
|
103
|
+
end
|
104
|
+
|
105
|
+
def raise_error_if_necessary(data)
|
106
|
+
if data.kind_of?(Hash)
|
107
|
+
if data.keys.size == 1 and data["error"]
|
108
|
+
type = data["error"]["type"]
|
109
|
+
message = data["error"]["message"]
|
110
|
+
raise Exception.new("#{type}: #{message}")
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|