ostatus 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,53 +1,55 @@
1
1
  module OStatus
2
+ ACTIVITY_NS = 'http://activitystrea.ms/spec/1.0/'
2
3
 
3
4
  # This class represents an Activity object for an OStatus entry.
4
5
  class Activity
6
+ SCHEMA_ROOT = 'http://activitystrea.ms/schema/1.0/'
5
7
 
6
- # This will create an instance of an Activity class populated
7
- # with the given data as a Hash or parsable XML given by a
8
- # Nokogiri::XML::Element that serves as the root node of
9
- # anything containing the activity tags.
10
- def initialize(activity_root)
11
- if activity_root.class == Hash
12
- @activity_data = activity_root
13
- @activity = nil
14
- else
15
- @activity = activity_root
16
- @activity_data = nil
17
- end
8
+ def initialize(entry)
9
+ @entry = entry
18
10
  end
19
11
 
20
- def pick_first_node(a)
21
- if a.empty?
22
- nil
23
- else
24
- a[0].content
25
- end
26
- end
27
- private :pick_first_node
28
-
29
12
  # Returns the object field or nil if it does not exist.
30
13
  def object
31
- return @activity_data[:object] unless @activity_data == nil
32
- pick_first_node(@activity.xpath('./activity:object'))
14
+ if @entry.is_a? Hash
15
+ @entry[:object]
16
+ else
17
+ @entry.activity_object
18
+ end
33
19
  end
34
20
 
35
21
  # Returns the target field or nil if it does not exist.
36
22
  def target
37
- return @activity_data[:target] unless @activity_data == nil
38
- pick_first_node(@activity.xpath('./activity:target'))
23
+ if @entry.is_a? Hash
24
+ @entry[:object]
25
+ else
26
+ @entry.activity_target
27
+ end
39
28
  end
40
29
 
41
30
  # Returns the verb field or nil if it does not exist.
31
+ # :favorite, :follow, :like, :"make-friend", :join, :play,
32
+ # :post, :save, :share, :tag, :update
42
33
  def verb
43
- return @activity_data[:verb] unless @activity_data == nil
44
- pick_first_node(@activity.xpath('./activity:verb'))
34
+ if @entry.is_a? Hash
35
+ @entry[:object]
36
+ else
37
+ obj = @entry.activity_verb
38
+ obj[SCHEMA_ROOT.size..-1].intern unless obj.nil?
39
+ end
45
40
  end
46
41
 
47
42
  # Returns the object-type field or nil if it does not exist.
43
+ # :article, :audio, :bookmark, :comment, :file, :folder, :group,
44
+ # :list, :note, :person, :photo, :"photo-album", :place, :playlist,
45
+ # :product, :review, :service, :status, :video
48
46
  def object_type
49
- return @activity_data[:object_type] unless @activity_data == nil
50
- pick_first_node(@activity.xpath('./activity:object-type'))
47
+ if @entry.is_a? Hash
48
+ @entry[:object_type]
49
+ else
50
+ obj = @entry.activity_object_type
51
+ obj[SCHEMA_ROOT.size..-1].intern unless obj.nil?
52
+ end
51
53
  end
52
54
 
53
55
  # Returns a hash of all relevant fields.
@@ -4,59 +4,85 @@ require_relative 'portable_contacts'
4
4
  module OStatus
5
5
 
6
6
  # Holds information about the author of the Feed.
7
- class Author
8
-
9
- # Instantiates an Author object either from a given <author></author> root
10
- # passed as an instance of a Nokogiri::XML::Element or a Hash containing
11
- # the properties.
12
- def initialize(author_node)
13
- if author_node.class == Hash
14
- @author_data = author_node
15
- @author = nil
16
- else
17
- @author = author_node
18
- @author_data = nil
19
- end
20
- end
7
+ class Author < Atom::Person
8
+ include Atom::SimpleExtensions
21
9
 
22
- # Gives an instance of an OStatus::Activity that parses the fields
23
- # having an activity prefix.
24
- def activity
25
- OStatus::Activity.new(@author)
26
- end
10
+ add_extension_namespace :activity, ACTIVITY_NS
11
+ element 'activity:object-type'
27
12
 
28
- def pick_first_node(a)
29
- if a.empty?
30
- nil
31
- else
32
- a[0].content
33
- end
13
+ namespace Atom::NAMESPACE
14
+ element :email
15
+ element :uri
16
+
17
+ add_extension_namespace :poco, POCO_NS
18
+ element 'poco:id'
19
+ element 'poco:displayName'
20
+ element 'poco:nickname'
21
+ element 'poco:updated', :class => DateTime, :content_only => true
22
+ element 'poco:published', :class => DateTime, :content_only => true
23
+ element 'poco:birthday', :class => Date, :content_only => true
24
+ element 'poco:anniversary', :class => Date, :content_only => true
25
+ element 'poco:gender'
26
+ element 'poco:note'
27
+ element 'poco:preferredUsername'
28
+ element 'poco:connected'
29
+
30
+ def initialize *args
31
+ self.activity_object_type = "http://activitystrea.ms/schema/1.0/person"
32
+ super(*args)
34
33
  end
35
- private :pick_first_node
36
34
 
37
- # Returns the name of the author, if it exists.
35
+ # unfortunately ratom doesn't handle elements with the same local name well.
36
+ # this is a workaround for that.
37
+ attr_writer :name, :poco_name
38
+
38
39
  def name
39
- return @author_data[:name] unless @author_data == nil
40
- pick_first_node(@author.css('name'))
40
+ @name or self[Atom::NAMESPACE, 'name'].first
41
+ end
42
+
43
+ def poco_name
44
+ @poco_name or self[POCO_NS, 'name'].first
41
45
  end
42
46
 
43
- # Returns the email of the author, if it exists.
44
- def email
45
- return @author_data[:email] unless @author_data == nil
46
- pick_first_node(@author.css('email'))
47
+ def to_xml(*args)
48
+ x = super(*args)
49
+
50
+ if self.name
51
+ node = XML::Node.new('name')
52
+ node << self.name
53
+ x << node
54
+ end
55
+
56
+ if self.poco_name
57
+ node = XML::Node.new('poco:name')
58
+ node << self.poco_name
59
+ x << node
60
+ end
61
+
62
+ x
47
63
  end
48
64
 
49
- # Returns the uri of the author, if it exists.
50
- def uri
51
- return @author_data[:uri] unless @author_data == nil
52
- pick_first_node(@author.css('uri'))
65
+ # Gives an instance of an OStatus::Activity that parses the fields
66
+ # having an activity prefix.
67
+ def activity
68
+ OStatus::Activity.new(self)
53
69
  end
54
70
 
55
71
  # Returns an instance of a PortableContacts that further describe the
56
72
  # author's contact information, if it exists.
57
73
  def portable_contacts
58
- return @author_data[:portable_contacts] unless @author_data == nil
59
- PortableContacts.new(@author)
74
+ PortableContacts.new(self)
75
+ end
76
+
77
+ def portable_contacts= poco
78
+ [ 'id', 'name', 'nickname', 'updated', 'published', 'birthday',
79
+ 'anniversary', 'gender', 'note', 'connected'].each do |p|
80
+ v = poco.send(p)
81
+ self.send("poco_#{p}=", v) if v
82
+ end
83
+
84
+ self.poco_displayName = poco.display_name if poco.display_name
85
+ self.poco_preferredUsername = poco.preferred_username if poco.preferred_username
60
86
  end
61
87
  end
62
88
  end
data/lib/ostatus/entry.rb CHANGED
@@ -1,131 +1,74 @@
1
1
  require_relative 'activity'
2
+ require_relative 'author'
2
3
 
3
4
  module OStatus
4
5
 
5
6
  # Holds information about an individual entry in the Feed.
6
- class Entry
7
+ class Entry < Atom::Entry
8
+ include Atom::SimpleExtensions
9
+
10
+ add_extension_namespace :activity, ACTIVITY_NS
11
+ element 'activity:object-type'
12
+ element 'activity:object'
13
+ element 'activity:verb'
14
+ element 'activity:target'
15
+
16
+ namespace Atom::NAMESPACE
17
+ element :title, :id, :summary
18
+ element :updated, :published, :class => DateTime, :content_only => true
19
+ element :source, :class => Atom::Source
20
+ elements :links, :class => Atom::Link
21
+ elements :categories, :class => Atom::Category
22
+ element :content, :class => Atom::Content
23
+ element :author, :class => OStatus::Author
7
24
 
8
- # Instantiates an Entry object from either a given <entry></entry> root
9
- # passed as an instance of a Nokogiri::XML::Element or a Hash
10
- # containing the properties.
11
- def initialize(entry_node)
12
- if entry_node.class == Hash
13
- @entry_data = entry_node
14
- @entry = nil
15
- else
16
- @entry = entry_node
17
- @entry_data = nil
18
- end
19
- end
20
-
21
- # Gives an instance of an OStatus::Activity that parses the fields
22
- # having an activity prefix.
23
25
  def activity
24
- Activity.new(@entry)
26
+ Activity.new(self)
25
27
  end
26
28
 
27
- def pick_first_node(a)
28
- if a.empty?
29
- nil
30
- else
31
- a[0].content
29
+ def activity= value
30
+ if value.object_type
31
+ self.activity_object_type = OStatus::Activity::SCHEMA_ROOT + value.object_type.to_s
32
32
  end
33
- end
34
- private :pick_first_node
35
-
36
- # Returns the title of the entry.
37
- def title
38
- return @entry_data[:title] unless @entry_data == nil
39
- pick_first_node(@entry.css('title'))
40
- end
41
-
42
- # Returns the content of the entry.
43
- def content
44
- return @entry_data[:content] unless @entry_data == nil
45
- pick_first_node(@entry.css('content'))
46
- end
47
-
48
- # Returns the content-type of the entry.
49
- def content_type
50
- return @entry_data[:content_type] unless @entry_data == nil
51
- content = @entry.css('content')
52
- content.empty? ? "" : content[0]['type']
53
- end
54
-
55
- # Returns the DateTime that this entry was published.
56
- def published
57
- return @entry_data[:published] unless @entry_data == nil
58
- DateTime.parse(pick_first_node(@entry.css('published')))
59
- end
60
-
61
- # Returns the DateTime that this entry was updated.
62
- def updated
63
- return @entry_data[:updated] unless @entry_data == nil
64
- DateTime.parse(pick_first_node(@entry.css('updated')))
65
- end
66
-
67
- # Returns the id of the entry.
68
- def id
69
- return @entry_data[:id] unless @entry_data == nil
70
- pick_first_node(@entry.css('id'))
33
+ self.activity_object = value.activity_object if value.object
34
+ if value.verb
35
+ self.activity_verb = OStatus::Activity::SCHEMA_ROOT + value.activity_verb.to_s
36
+ end
37
+ self.activity_target = value.activity_target if value.target
38
+ activity_object_type = "HEY"
71
39
  end
72
40
 
73
41
  def url
74
- return @entry_data[:url] unless @entry_data == nil or @entry_data[:url] == nil
75
- return nil if @entry_data != nil
76
-
77
- cur_url = nil
78
- @entry.css('link').each do |node|
79
- if node[:href]
80
- cur_url = node[:href]
81
- end
82
- end
83
-
84
- links = self.link
85
- if links[:alternate]
86
- links[:alternate][0][:href].value
87
- elsif links[:self]
88
- links[:self][0][:href].value
42
+ if links.alternate
43
+ links.alternate.href
44
+ elsif links.self
45
+ links.self.href
89
46
  else
90
- cur_url
47
+ links.map.each do |l|
48
+ l.href
49
+ end.compact.first
91
50
  end
92
51
  end
93
52
 
94
- def link
95
- return @entry_data[:link] unless @entry_data == nil
96
-
97
- result = {}
98
-
99
- @entry.css('link').each do |node|
100
- if node[:rel] != nil
101
- rel = node[:rel].intern
102
- if result[rel] == nil
103
- result[rel] = []
104
- end
105
-
106
- attrs = node.attributes
107
-
108
- map = {}
109
- attrs.keys.each do |key|
110
- map[key.intern] = attrs[key]
111
- end
53
+ def url= value
54
+ links << Atom::Link.new(:rel => "alternate", :href => value)
55
+ end
112
56
 
113
- result[rel] << map
114
- end
115
- end
57
+ def link
58
+ links.group_by { |l| l.rel.intern }
59
+ end
116
60
 
117
- result
61
+ def link= options
62
+ links.clear << Atom::Link.new(options)
118
63
  end
119
64
 
120
65
  # Returns a Hash of all fields.
121
66
  def info
122
- return @entry_data unless @entry_data == nil
123
67
  {
124
68
  :activity => self.activity.info,
125
- :id => pick_first_node(@entry.css('id')),
69
+ :id => self.id,
126
70
  :title => self.title,
127
71
  :content => self.content,
128
- :content_type => self.content_type,
129
72
  :link => self.link,
130
73
  :published => self.published,
131
74
  :updated => self.updated
data/lib/ostatus/feed.rb CHANGED
@@ -1,6 +1,5 @@
1
- require 'nokogiri'
2
1
  require 'open-uri'
3
- require 'tinyatom'
2
+ require 'atom'
4
3
 
5
4
  require_relative 'entry'
6
5
  require_relative 'author'
@@ -8,22 +7,49 @@ require_relative 'author'
8
7
  module OStatus
9
8
 
10
9
  # This class represents an OStatus Feed object.
11
- class Feed
10
+ class Feed < Atom::Feed
11
+ include Atom::SimpleExtensions
12
+
13
+ namespace Atom::NAMESPACE
14
+
15
+ add_extension_namespace :poco, POCO_NS
16
+ add_extension_namespace :poco, ACTIVITY_NS
17
+ element :id, :rights, :icon, :logo
18
+ element :generator, :class => Atom::Generator
19
+ element :title, :subtitle, :class => Atom::Content
20
+ element :updated, :class => Time, :content_only => true
21
+ elements :links, :class => Atom::Link
22
+ elements :authors, :class => OStatus::Author
23
+ elements :categories, :class => Atom::Category
24
+ elements :entries, :class => OStatus::Entry
25
+
26
+ attr_reader :url
27
+
12
28
  def initialize(str, url, access_token, options)
13
29
  @str = str
14
30
  @url = url
15
31
  @access_token = access_token
16
32
  @options = options
17
33
 
18
- if options == nil
19
- @xml = Nokogiri::XML::Document.parse(self.atom)
34
+ if str
35
+ super(XML::Reader.string(str))
36
+ else
37
+ super(options)
20
38
  end
21
39
  end
22
40
 
23
41
  # Creates a new Feed instance given by the atom feed located at 'url'
24
42
  # and optionally using the OAuth::AccessToken given.
25
43
  def Feed.from_url(url, access_token = nil)
26
- Feed.new(nil, url, access_token, nil)
44
+ if access_token.nil?
45
+ # simply open the url
46
+ str = open(url).read
47
+ else
48
+ # open the url through OAuth
49
+ str = access_token.get(url).body
50
+ end
51
+
52
+ Feed.new(str, url, access_token, nil)
27
53
  end
28
54
 
29
55
  # Creates a new Feed instance that contains the information given by
@@ -36,52 +62,34 @@ module OStatus
36
62
  Feed.new(str, nil, nil, nil)
37
63
  end
38
64
 
39
- # Returns an array of Nokogiri::XML::Element instances for all link tags
40
- # that have a rel equal to that given by attribute. This can be used
41
- # generally as a Hash where the keys are intern strings that give an attribute.
65
+ # Returns an array of Atom::Link instances for all link tags
66
+ # that have a rel equal to that given by attribute.
42
67
  #
43
68
  # For example:
44
- # link(:hub).first[:href] -- Gets the first link tag with rel="hub" and
45
- # returns the contents of the href attribute.
69
+ # link(:hub).first.href -- Gets the first link tag with rel="hub" and
70
+ # returns the contents of the href attribute.
46
71
  #
47
72
  def link(attribute)
48
- return @options[:links][attribute] unless @options == nil or @options[:links] == nil
49
- return nil if @options != nil
73
+ links.find_all { |l| l.rel == attribute.to_s }
74
+ end
50
75
 
51
- # get all links with rel attribute being equal to attribute
52
- @xml.xpath('/xmlns:feed/xmlns:link').select do |link|
53
- link[:rel] == attribute.to_s
76
+ def links=(given)
77
+ self.links.clear
78
+ given.each do |rel,links|
79
+ links.each do |l|
80
+ self.links << Atom::Link.new(l.merge({:rel => rel}))
81
+ end
54
82
  end
55
83
  end
56
84
 
57
85
  # Returns an array of URLs for each hub link tag.
58
86
  def hubs
59
- if link(:hub)
60
- link(:hub).map do |link|
61
- link[:href]
62
- end
63
- else
64
- []
65
- end
87
+ link(:hub).map { |link| link.href }
66
88
  end
67
89
 
68
90
  # Returns the salmon URL from the link tag.
69
91
  def salmon
70
- link(:salmon).first[:href]
71
- end
72
-
73
- # Returns the logo
74
- def logo
75
- return @options[:logo] unless @options == nil
76
-
77
- pick_first_node(@xml.xpath('/xmlns:feed/xmlns:logo'))
78
- end
79
-
80
- # Returns the icon
81
- def icon
82
- return @options[:icon] unless @options == nil
83
-
84
- pick_first_node(@xml.xpath('/xmlns:feed/xmlns:icon'))
92
+ link(:salmon).first.href
85
93
  end
86
94
 
87
95
  # This method will return a String containing the actual content of
@@ -97,88 +105,25 @@ module OStatus
97
105
  # open the url through OAuth
98
106
  @access_token.get(@url).body
99
107
  else
100
- # build the atom file from internal information
101
- feed = TinyAtom::Feed.new(
102
- self.id,
103
- self.title,
104
-
105
- @url,
106
-
107
- :author_name => self.author.name,
108
- :author_email => self.author.email,
109
- :author_uri => self.author.uri,
110
-
111
- :hubs => self.hubs
112
- )
113
-
114
- @options[:entries].each do |entry|
115
- entry_url = entry.url
116
- entry_url = @url if entry_url == nil
117
-
118
- feed.add_entry(
119
- entry.id,
120
- entry.title,
121
- entry.updated,
122
-
123
- entry_url,
124
-
125
- :published => entry.published,
126
-
127
- :content => entry.content,
128
-
129
- :author_name => self.author.name,
130
- :author_email => self.author.email,
131
- :author_uri => self.author.uri
132
- )
133
- end
134
-
135
- feed.make(:indent => 2)
136
- end
137
- end
138
-
139
- def pick_first_node(a)
140
- if a.empty?
141
- nil
142
- else
143
- a[0].content
108
+ self.links << Atom::Link.new(:rel => 'self', :href => @url) if @url
109
+ self.links << Atom::Link.new(:rel => 'edit', :href => @url) if @url
110
+ self.to_xml
144
111
  end
145
112
  end
146
- private :pick_first_node
147
-
148
- def id
149
- return @options[:id] unless @options == nil
150
-
151
- pick_first_node(@xml.xpath('/xmlns:feed/xmlns:id'))
152
- end
153
-
154
- def title
155
- return @options[:title] unless @options == nil
156
-
157
- pick_first_node(@xml.xpath('/xmlns:feed/xmlns:title'))
158
- end
159
-
160
- def url
161
- return @url
162
- end
163
113
 
164
114
  # Returns an OStatus::Author that will parse the author information
165
115
  # within the Feed.
166
116
  def author
167
- return @options[:author] unless @options == nil
168
-
169
- author_xml = @xml.at_css('author')
170
- OStatus::Author.new(author_xml)
117
+ @options ? @options[:author] : self.authors.first
171
118
  end
172
119
 
173
- # This method gives you an array of OStatus::Entry instances for
174
- # each entry listed in the feed.
175
- def entries
176
- return @options[:entries] unless @options == nil
177
-
178
- entries_xml = @xml.css('entry')
120
+ def author= author
121
+ self.authors.clear << author
122
+ end
179
123
 
180
- entries_xml.map do |entry|
181
- OStatus::Entry.new(entry)
124
+ def hubs= hubs
125
+ hubs.each do |hub|
126
+ links << Atom::Link.new(:rel => 'hub', :href => hub)
182
127
  end
183
128
  end
184
129
  end
@@ -1,116 +1,59 @@
1
1
  module OStatus
2
+ POCO_NS = 'http://portablecontacts.net/spec/1.0'
2
3
 
3
4
  # Holds information about the extended contact information
4
5
  # in the Feed given in the Portable Contacts specification.
5
6
  class PortableContacts
6
-
7
- # Instantiates a OStatus::PortableContacts object from either
8
- # a given root that contains all <poco:*> tags as a
9
- # Nokogiri::XML::Element or a Hash containing the properties.
10
- def initialize(author_node)
11
- if author_node.class == Hash
12
- @poco_data = author_node
13
- @poco = nil
14
- else
15
- @poco = author_node
16
- @poco_data = nil
17
- end
18
- end
19
7
 
20
- def pick_first_node(a)
21
- if a.empty?
22
- nil
8
+ # Instantiates a OStatus::PortableContacts object from either
9
+ # a given root that contains all <poco:*> tags as an ratom Person
10
+ # or a Hash containing the properties.
11
+ def initialize(parent)
12
+ if parent.is_a? Hash
13
+ @options = parent
23
14
  else
24
- a[0].content
15
+ @parent = parent
25
16
  end
26
17
  end
27
- private :pick_first_node
28
-
29
- # Returns the id of the contact, if it exists.
30
- def id
31
- return @poco_data[:id] unless @poco_data == nil
32
- pick_first_node(@poco.xpath('./poco:id'))
33
- end
34
18
 
35
- # Returns the display_name of the contact, if it exists.
36
- def display_name
37
- return @poco_data[:display_name] unless @poco_data == nil
38
- pick_first_node(@poco.xpath('./poco:displayName'))
39
- end
19
+ def id; get_prop(:id); end
20
+ def id= value; set_prop(:id, value); end
40
21
 
41
- # Returns the name of the contact, if it exists.
42
- def name
43
- return @poco_data[:name] unless @poco_data == nil
44
- pick_first_node(@poco.xpath('./poco:name'))
45
- end
22
+ def name; get_prop(:name); end
23
+ def name= value; set_prop(:name, value); end
46
24
 
47
- # Returns the nickname of the contact, if it exists.
48
- def nickname
49
- return @poco_data[:nickname] unless @poco_data == nil
50
- pick_first_node(@poco.xpath('./poco:nickname'))
51
- end
25
+ def nickname; get_prop(:nickname); end
26
+ def nickname= value; set_prop(:nickname, value); end
52
27
 
53
- # Returns the published of the contact, if it exists.
54
- def published
55
- return @poco_data[:published] unless @poco_data == nil
56
- pub = pick_first_node(@poco.xpath('./poco:published'))
57
- if pub != nil
58
- DateTime.parse(pub)
59
- end
60
- end
28
+ def gender; get_prop(:gender); end
29
+ def gender= value; set_prop(:gender, value); end
61
30
 
62
- # Returns the updated of the contact, if it exists.
63
- def updated
64
- return @poco_data[:updated] unless @poco_data == nil
65
- upd = pick_first_node(@poco.xpath('./poco:updated'))
66
- if upd != nil
67
- DateTime.parse(upd)
68
- end
69
- end
31
+ def note; get_prop(:note); end
32
+ def note= value; set_prop(:note, value); end
70
33
 
71
- # Returns the birthday of the contact, if it exists.
72
- def birthday
73
- return @poco_data[:birthday] unless @poco_data == nil
74
- bday = pick_first_node(@poco.xpath('./poco:birthday'))
75
- if bday != nil
76
- Date.parse(bday)
77
- end
78
- end
34
+ def display_name; get_prop(:display_name, 'displayName'); end
35
+ def display_name= value; set_prop(:display_name, value, 'displayName'); end
79
36
 
80
- # Returns the anniversary of the contact, if it exists.
81
- def anniversary
82
- return @poco_data[:anniversary] unless @poco_data == nil
83
- anni = pick_first_node(@poco.xpath('./poco:anniversary'))
84
- if anni != nil
85
- Date.parse(anni)
86
- end
37
+ def preferred_username
38
+ get_prop(:preferred_username, 'preferredUsername')
87
39
  end
88
40
 
89
- # Returns the gender of the contact, if it exists.
90
- def gender
91
- return @poco_data[:gender] unless @poco_data == nil
92
- pick_first_node(@poco.xpath('./poco:gender'))
41
+ def preferred_username= value
42
+ set_prop(:preferred_username, value, 'preferredUsername')
93
43
  end
94
44
 
95
- # Returns the note of the contact, if it exists.
96
- def note
97
- return @poco_data[:note] unless @poco_data == nil
98
- pick_first_node(@poco.xpath('./poco:note'))
99
- end
45
+ def updated; get_datetime(:updated); end
46
+ def published; get_datetime(:published); end
100
47
 
101
- # Returns the preferred username of the contact, if it exists.
102
- def preferred_username
103
- return @poco_data[:preferred_username] unless @poco_data == nil
104
- pick_first_node(@poco.xpath('./poco:preferredUsername'))
105
- end
48
+ def birthday; get_date(:birthday); end
49
+ def anniversary; get_date(:anniversary); end
106
50
 
107
51
  # Returns a boolean that indicates that a bi-directional connection
108
52
  # has been established between the user and the contact, if it is
109
53
  # able to assert this.
110
54
  def connected
111
- return @poco_data[:connected] unless @poco_data == nil
112
- str = pick_first_node(@poco.xpath('./poco:connected'))
113
- return nil if str == nil
55
+ return @options[:connected] unless @options.nil?
56
+ str = @parent.poco_connected
114
57
 
115
58
  if str == "true"
116
59
  true
@@ -120,5 +63,38 @@ module OStatus
120
63
  nil
121
64
  end
122
65
  end
66
+
67
+ private
68
+
69
+ def get_prop name, xmlName = name
70
+ @options ? @options[name] : @parent.send("poco_#{xmlName}")
71
+ end
72
+
73
+ def set_prop name, value, xmlName = name
74
+ if @options
75
+ @options[name] = value
76
+ else
77
+ @parent.send("poco_#{xmlName}=", value)
78
+ end
79
+ end
80
+
81
+ def get_datetime x
82
+ if @options
83
+ dt = @options[x]
84
+ DateTime.parse(dt) if dt
85
+ else
86
+ @parent.send("poco_#{x}")
87
+ end
88
+ end
89
+
90
+ def get_date x
91
+ if @options
92
+ d = @options[x]
93
+ Date.parse(d) if d
94
+ else
95
+ @parent.send("poco_#{x}")
96
+ end
97
+ end
98
+
123
99
  end
124
100
  end
@@ -1,3 +1,3 @@
1
1
  module OStatus
2
- VERSION = "0.0.6"
2
+ VERSION = "0.0.7"
3
3
  end
data/lib/ostatus.rb CHANGED
@@ -1,5 +1,3 @@
1
- require 'nokogiri'
2
-
3
1
  require_relative 'ostatus/feed'
4
2
  require_relative 'ostatus/entry'
5
3
  require_relative 'ostatus/author'
data/ostatus.gemspec CHANGED
@@ -15,8 +15,7 @@ Gem::Specification.new do |s|
15
15
  s.rubyforge_project = "ostatus"
16
16
 
17
17
  s.add_dependency "oauth"
18
- s.add_dependency "nokogiri"
19
- s.add_dependency "tinyatom"
18
+ s.add_dependency "ratom"
20
19
  s.add_development_dependency "rspec"
21
20
 
22
21
  s.files = `git ls-files`.split("\n")
@@ -23,7 +23,7 @@ describe OStatus::Activity do
23
23
 
24
24
  describe "#object-type" do
25
25
  it "should give a String containing the content of the activity:object-type tag" do
26
- @activity.object_type.should eql('http://activitystrea.ms/schema/1.0/note')
26
+ @activity.object_type.should eql(:note)
27
27
  end
28
28
 
29
29
  it "should give nil when no activity:object-type was given" do
@@ -33,7 +33,7 @@ describe OStatus::Activity do
33
33
 
34
34
  describe "#verb" do
35
35
  it "should give a String containing the content of the activity:verb tag" do
36
- @activity.verb.should eql('http://activitystrea.ms/schema/1.0/post')
36
+ @activity.verb.should eql(:post)
37
37
  end
38
38
 
39
39
  it "should give nil when no activity:verb was given" do
data/spec/author_spec.rb CHANGED
@@ -16,7 +16,7 @@ describe OStatus::Author do
16
16
  end
17
17
 
18
18
  it "should give an Activity instance that is relevant to the author subtree" do
19
- @author.activity.object_type.should eql('http://activitystrea.ms/schema/1.0/person')
19
+ @author.activity.object_type.should eql(:person)
20
20
  end
21
21
  end
22
22
 
@@ -0,0 +1,72 @@
1
+ require_relative '../lib/ostatus/feed.rb'
2
+
3
+ describe 'XML builder' do
4
+ before(:each) do
5
+ @feed_url = 'http://example.org/feed'
6
+ @poco_id = '68b329da9893e34099c7d8ad5cb9c940'
7
+ @poco = OStatus::PortableContacts.new(:id => @poco_id,
8
+ :display_name => 'Dean Venture',
9
+ :preferred_username => 'dean')
10
+ @author = OStatus::Author.new(:name => 'Dean Venture',
11
+ :email => 'dean@venture.com',
12
+ :uri => 'http://geocities.com/~dean',
13
+ :portable_contacts => @poco)
14
+ @feed = OStatus::Feed.from_data(@feed_url,
15
+ :title => "Dean's Updates",
16
+ :id => @feed_url,
17
+ :author => @author,
18
+ :entries => [],
19
+ :links => {
20
+ :hub => [{:href => 'http://example.org/hub'}]
21
+ })
22
+ end
23
+
24
+ it 'should generate the title' do
25
+ @feed.atom.should match("<title>Dean's Updates")
26
+ end
27
+
28
+ it 'should generate the id' do
29
+ @feed.atom.should match("<id>#{@feed_url}")
30
+ end
31
+
32
+ it 'should generate a self link' do
33
+ # depending on this attribute order is a really terrible idea, but oh well.
34
+ @feed.atom.should match("<link rel=\"self\" href=\"#{@feed_url}\"/>")
35
+ end
36
+
37
+ it 'should generate the hub link' do
38
+ # depending on this attribute order is a really terrible idea, but oh well.
39
+ @feed.atom.should match('<link rel="hub" href="http://example.org/hub"/>')
40
+ end
41
+
42
+ describe 'when generating the author' do
43
+ specify { @feed.atom.should match('<name>Dean Venture') }
44
+ specify { @feed.atom.should match('<email>dean@venture.com') }
45
+ specify { @feed.atom.should match('<uri>http://geocities.com/~dean') }
46
+ specify { @feed.atom.should match("<poco:id>#{@poco_id}") }
47
+ specify { @feed.atom.should match('<poco:displayName>Dean Venture') }
48
+ specify { @feed.atom.should match('<poco:preferredUsername>dean') }
49
+ end
50
+
51
+ describe 'when generating a feed with entries' do
52
+ before do
53
+ @now = Time.now
54
+
55
+ @feed.entries << OStatus::Entry.new(
56
+ :title => 'atom powered robots are running amok lol',
57
+ :content => 'atom powered robots are running amok lol',
58
+ :updated => @now,
59
+ :published => @now,
60
+ :id => 'http://example.org/feed/1',
61
+ :link => { :href => 'http://example.org/feed/1' }
62
+ )
63
+ end
64
+
65
+ specify { @feed.atom.should match('<title>atom powered robots') }
66
+ specify { @feed.atom.should match('<content>atom powered robots') }
67
+ specify { @feed.atom.should match("<updated>#{@now.iso8601}") }
68
+ specify { @feed.atom.should match("<published>#{@now.iso8601}") }
69
+ specify { @feed.atom.should match('<id>http://example.org/feed/1') }
70
+ specify { @feed.atom.should match('<link href="http://example.org/feed/1"/>') }
71
+ end
72
+ end
data/spec/entry_spec.rb CHANGED
@@ -26,12 +26,6 @@ describe OStatus::Entry do
26
26
  end
27
27
  end
28
28
 
29
- describe "#content_type" do
30
- it "should give a String containing the content of the type attribute on the content tag" do
31
- @entry.content_type.should eql("html")
32
- end
33
- end
34
-
35
29
  describe "#updated" do
36
30
  it "should return a DateTime instance" do
37
31
  @entry.updated.instance_of?(DateTime).should eql(true)
@@ -58,12 +52,6 @@ describe OStatus::Entry do
58
52
  end
59
53
  end
60
54
 
61
- describe "#url" do
62
- it "should return a String" do
63
- @entry.url.class.should eql(String)
64
- end
65
- end
66
-
67
55
  describe "#info" do
68
56
  it "should give a Hash" do
69
57
  @entry.info.instance_of?(Hash).should eql(true)
@@ -81,10 +69,6 @@ describe OStatus::Entry do
81
69
  @entry.info[:title].should eql("staples come out of the head tomorrow, oh yeah")
82
70
  end
83
71
 
84
- it "should contain the content_type" do
85
- @entry.info[:content_type].should eql("html")
86
- end
87
-
88
72
  it "should contain a Hash for the link" do
89
73
  @entry.info[:link].class.should eql(Hash)
90
74
  end
@@ -22,11 +22,11 @@
22
22
  <poco:id>foobar</poco:id>
23
23
  <poco:name>barbaz</poco:name>
24
24
  <poco:nickname>spaz</poco:nickname>
25
- <poco:published>2012-02-21T02:15:14+00:00</pico:published>
26
- <poco:updated>2013-02-21T02:15:14+00:00</pico:updated>
27
- <poco:birthday>2014-02-21</pico:birthday>
28
- <poco:anniversary>2015-02-21</pico:anniversary>
29
- <poco:gender>male</pico:gender>
25
+ <poco:published>2012-02-21T02:15:14+00:00</poco:published>
26
+ <poco:updated>2013-02-21T02:15:14+00:00</poco:updated>
27
+ <poco:birthday>2014-02-21</poco:birthday>
28
+ <poco:anniversary>2015-02-21</poco:anniversary>
29
+ <poco:gender>male</poco:gender>
30
30
  <poco:note>foo
31
31
  bar</poco:note>
32
32
  <poco:utcOffset>-08:00</poco:utcOffset>
@@ -72,7 +72,7 @@ bar</poco:note>
72
72
  <entry>
73
73
  <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
74
74
  <activity:object>Foobar</activity:object>
75
- <activity:target>Barbaz</activity:object>
75
+ <activity:target>Barbaz</activity:target>
76
76
  <id>http://identi.ca/notice/64991641</id>
77
77
  <title>staples come out of the head tomorrow, oh yeah</title>
78
78
  <content type="html">staples come out of the head tomorrow, oh yeah</content>
@@ -48,7 +48,7 @@
48
48
  <entry>
49
49
  <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
50
50
  <activity:object>Foobar</activity:object>
51
- <activity:target>Barbaz</activity:object>
51
+ <activity:target>Barbaz</activity:target>
52
52
  <id>http://identi.ca/notice/64991641</id>
53
53
  <title>staples come out of the head tomorrow, oh yeah</title>
54
54
  <content type="html">staples come out of the head tomorrow, oh yeah</content>
@@ -22,11 +22,11 @@
22
22
  <poco:id>foobar</poco:id>
23
23
  <poco:name>barbaz</poco:name>
24
24
  <poco:nickname>spaz</poco:nickname>
25
- <poco:published>2012-02-21T02:15:14+00:00</pico:published>
26
- <poco:updated>2013-02-21T02:15:14+00:00</pico:updated>
27
- <poco:birthday>2014-02-21</pico:birthday>
28
- <poco:anniversary>2015-02-21</pico:anniversary>
29
- <poco:gender>male</pico:gender>
25
+ <poco:published>2012-02-21T02:15:14+00:00</poco:published>
26
+ <poco:updated>2013-02-21T02:15:14+00:00</poco:updated>
27
+ <poco:birthday>2014-02-21</poco:birthday>
28
+ <poco:anniversary>2015-02-21</poco:anniversary>
29
+ <poco:gender>male</poco:gender>
30
30
  <poco:note>foo
31
31
  bar</poco:note>
32
32
  <poco:utcOffset>-08:00</poco:utcOffset>
@@ -71,7 +71,7 @@ bar</poco:note>
71
71
  <entry>
72
72
  <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
73
73
  <activity:object>Foobar</activity:object>
74
- <activity:target>Barbaz</activity:object>
74
+ <activity:target>Barbaz</activity:target>
75
75
  <id>http://identi.ca/notice/64991641</id>
76
76
  <title>staples come out of the head tomorrow, oh yeah</title>
77
77
  <content type="html">staples come out of the head tomorrow, oh yeah</content>
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 6
9
- version: 0.0.6
8
+ - 7
9
+ version: 0.0.7
10
10
  platform: ruby
11
11
  authors:
12
12
  - Hackers of the Severed Hand
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-03-22 00:00:00 -04:00
17
+ date: 2011-04-02 00:00:00 -04:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -31,7 +31,7 @@ dependencies:
31
31
  type: :runtime
32
32
  version_requirements: *id001
33
33
  - !ruby/object:Gem::Dependency
34
- name: nokogiri
34
+ name: ratom
35
35
  prerelease: false
36
36
  requirement: &id002 !ruby/object:Gem::Requirement
37
37
  none: false
@@ -43,23 +43,10 @@ dependencies:
43
43
  version: "0"
44
44
  type: :runtime
45
45
  version_requirements: *id002
46
- - !ruby/object:Gem::Dependency
47
- name: tinyatom
48
- prerelease: false
49
- requirement: &id003 !ruby/object:Gem::Requirement
50
- none: false
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- segments:
55
- - 0
56
- version: "0"
57
- type: :runtime
58
- version_requirements: *id003
59
46
  - !ruby/object:Gem::Dependency
60
47
  name: rspec
61
48
  prerelease: false
62
- requirement: &id004 !ruby/object:Gem::Requirement
49
+ requirement: &id003 !ruby/object:Gem::Requirement
63
50
  none: false
64
51
  requirements:
65
52
  - - ">="
@@ -68,7 +55,7 @@ dependencies:
68
55
  - 0
69
56
  version: "0"
70
57
  type: :development
71
- version_requirements: *id004
58
+ version_requirements: *id003
72
59
  description: This project is to be used to jumpstart OStatus related projects that implement the PubSubHubbub protocols by providing the common fundamentals of Atom parsing and OStatus object creation.
73
60
  email:
74
61
  - hotsh@xomb.org
@@ -93,6 +80,7 @@ files:
93
80
  - ostatus.gemspec
94
81
  - spec/activity_spec.rb
95
82
  - spec/author_spec.rb
83
+ - spec/builder_spec.rb
96
84
  - spec/entry_spec.rb
97
85
  - spec/feed_spec.rb
98
86
  - spec/portable_contacts_spec.rb
@@ -134,6 +122,7 @@ summary: Implementations of the OStatus data stream objects.
134
122
  test_files:
135
123
  - spec/activity_spec.rb
136
124
  - spec/author_spec.rb
125
+ - spec/builder_spec.rb
137
126
  - spec/entry_spec.rb
138
127
  - spec/feed_spec.rb
139
128
  - spec/portable_contacts_spec.rb