titi 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (190) hide show
  1. data/README.textile +23 -4
  2. data/VERSION +1 -1
  3. data/examples/twitter.rb +4 -12
  4. data/lib/titi.rb +6 -0
  5. data/lib/titi/fetcher.rb +5 -0
  6. data/lib/titi/fetcher/json.rb +32 -0
  7. data/lib/titi/provider.rb +0 -23
  8. data/lib/titi/provider/activity_streams.rb +10 -139
  9. data/lib/titi/provider/activity_streams/activity_streams_struct.rb +46 -0
  10. data/lib/titi/provider/activity_streams/actor.rb +11 -0
  11. data/lib/titi/provider/activity_streams/address.rb +11 -0
  12. data/lib/titi/provider/activity_streams/entry.rb +38 -0
  13. data/lib/titi/provider/activity_streams/feed.rb +25 -0
  14. data/lib/titi/provider/activity_streams/feed.xml.erb +13 -11
  15. data/lib/titi/provider/activity_streams/link.rb +15 -0
  16. data/lib/titi/provider/activity_streams/obj.rb +19 -0
  17. data/lib/titi/provider/ameba/.gitignore +0 -0
  18. data/lib/titi/provider/avatars_united/.gitignore +0 -0
  19. data/lib/titi/provider/baidu/.gitignore +0 -0
  20. data/lib/titi/provider/bebo/.gitignore +0 -0
  21. data/lib/titi/provider/blipfm/.gitignore +0 -0
  22. data/lib/titi/provider/blippr/.gitignore +0 -0
  23. data/lib/titi/provider/bliptv/.gitignore +0 -0
  24. data/lib/titi/provider/blogger/.gitignore +0 -0
  25. data/lib/titi/provider/brightkite/.gitignore +0 -0
  26. data/lib/titi/provider/buzznet/.gitignore +0 -0
  27. data/lib/titi/provider/cinchcast/.gitignore +0 -0
  28. data/lib/titi/provider/corkd/.gitignore +0 -0
  29. data/lib/titi/provider/daily_motion/.gitignore +0 -0
  30. data/lib/titi/provider/delicious/.gitignore +0 -0
  31. data/lib/titi/provider/deviant_art/.gitignore +0 -0
  32. data/lib/titi/provider/digg/.gitignore +0 -0
  33. data/lib/titi/provider/diigo/.gitignore +0 -0
  34. data/lib/titi/provider/douban/.gitignore +0 -0
  35. data/lib/titi/provider/flickr/.gitignore +0 -0
  36. data/lib/titi/provider/flixster/.gitignore +0 -0
  37. data/lib/titi/provider/fotolog/.gitignore +0 -0
  38. data/lib/titi/provider/friendfeed/.gitignore +0 -0
  39. data/lib/titi/provider/friendster/.gitignore +0 -0
  40. data/lib/titi/provider/funny_or_die/.gitignore +0 -0
  41. data/lib/titi/provider/gamer_dna/.gitignore +0 -0
  42. data/lib/titi/provider/gather/.gitignore +0 -0
  43. data/lib/titi/provider/generic_feed.rb +49 -0
  44. data/lib/titi/provider/generic_feed/.gitignore +0 -0
  45. data/lib/titi/provider/goodreads/.gitignore +0 -0
  46. data/lib/titi/provider/google_reader/.gitignore +0 -0
  47. data/lib/titi/provider/hatena/.gitignore +0 -0
  48. data/lib/titi/provider/hi5/.gitignore +0 -0
  49. data/lib/titi/provider/hulu/.gitignore +0 -0
  50. data/lib/titi/provider/hyves/.gitignore +0 -0
  51. data/lib/titi/provider/identica/.gitignore +0 -0
  52. data/lib/titi/provider/ilike/.gitignore +0 -0
  53. data/lib/titi/provider/jaiku/.gitignore +0 -0
  54. data/lib/titi/provider/joost/.gitignore +0 -0
  55. data/lib/titi/provider/lastfm/.gitignore +0 -0
  56. data/lib/titi/provider/librarything/.gitignore +0 -0
  57. data/lib/titi/provider/list_of_providers.rb +142 -0
  58. data/lib/titi/provider/livejournal/.gitignore +0 -0
  59. data/lib/titi/provider/meneame/.gitignore +0 -0
  60. data/lib/titi/provider/metacafe/.gitignore +0 -0
  61. data/lib/titi/provider/mixx/.gitignore +0 -0
  62. data/lib/titi/provider/moby_picture/.gitignore +0 -0
  63. data/lib/titi/provider/multiply/.gitignore +0 -0
  64. data/lib/titi/provider/netlog/.gitignore +0 -0
  65. data/lib/titi/provider/newsvine/.gitignore +0 -0
  66. data/lib/titi/provider/pandora/.gitignore +0 -0
  67. data/lib/titi/provider/photobucket/.gitignore +0 -0
  68. data/lib/titi/provider/photocase/.gitignore +0 -0
  69. data/lib/titi/provider/picasa/.gitignore +0 -0
  70. data/lib/titi/provider/plurk/.gitignore +0 -0
  71. data/lib/titi/provider/posterous/.gitignore +0 -0
  72. data/lib/titi/provider/propeller/.gitignore +0 -0
  73. data/lib/titi/provider/qik/.gitignore +0 -0
  74. data/lib/titi/provider/qype/.gitignore +0 -0
  75. data/lib/titi/provider/raptr/.gitignore +0 -0
  76. data/lib/titi/provider/readernaut/.gitignore +0 -0
  77. data/lib/titi/provider/reddit/.gitignore +0 -0
  78. data/lib/titi/provider/revver/.gitignore +0 -0
  79. data/lib/titi/provider/skyrock/.gitignore +0 -0
  80. data/lib/titi/provider/slideshare/.gitignore +0 -0
  81. data/lib/titi/provider/smotri/.gitignore +0 -0
  82. data/lib/titi/provider/smugmug/.gitignore +0 -0
  83. data/lib/titi/provider/stumbleupon/.gitignore +0 -0
  84. data/lib/titi/provider/tumblr/.gitignore +0 -0
  85. data/lib/titi/provider/twelve_seconds/.gitignore +0 -0
  86. data/lib/titi/provider/twine/.gitignore +0 -0
  87. data/lib/titi/provider/twitter.rb +18 -15
  88. data/lib/titi/provider/twitter/.gitignore +0 -0
  89. data/lib/titi/provider/{twitter_rss → twitter}/README.textile +0 -0
  90. data/lib/titi/provider/twitter/models.rb +9 -11
  91. data/lib/titi/provider/{twitter_rss/models.rb → twitter/rss_feed.rb} +9 -10
  92. data/lib/titi/provider/vimeo/.gitignore +0 -0
  93. data/lib/titi/provider/visualizeus/.gitignore +0 -0
  94. data/lib/titi/provider/wordpress/.gitignore +0 -0
  95. data/lib/titi/provider/xanga/.gitignore +0 -0
  96. data/lib/titi/provider/yelp/.gitignore +0 -0
  97. data/lib/titi/provider/zooomr/.gitignore +0 -0
  98. data/spec/data/provider/ameba/.gitignore +0 -0
  99. data/spec/data/provider/avatars_united/.gitignore +0 -0
  100. data/spec/data/provider/baidu/.gitignore +0 -0
  101. data/spec/data/provider/bebo/.gitignore +0 -0
  102. data/spec/data/provider/blipfm/.gitignore +0 -0
  103. data/spec/data/provider/blippr/.gitignore +0 -0
  104. data/spec/data/provider/bliptv/.gitignore +0 -0
  105. data/spec/data/provider/blogger/.gitignore +0 -0
  106. data/spec/data/provider/brightkite/.gitignore +0 -0
  107. data/spec/data/provider/buzznet/.gitignore +0 -0
  108. data/spec/data/provider/cinchcast/.gitignore +0 -0
  109. data/spec/data/provider/corkd/.gitignore +0 -0
  110. data/spec/data/provider/daily_motion/.gitignore +0 -0
  111. data/spec/data/provider/delicious/.gitignore +0 -0
  112. data/spec/data/provider/delicious/delicious_bookmarks-activity_streams.xml +440 -0
  113. data/spec/data/provider/delicious/delicious_bookmarks-raw_feed.xml +239 -0
  114. data/spec/data/provider/deviant_art/.gitignore +0 -0
  115. data/spec/data/provider/digg/.gitignore +0 -0
  116. data/spec/data/provider/diigo/.gitignore +0 -0
  117. data/spec/data/provider/douban/.gitignore +0 -0
  118. data/spec/data/provider/flickr/.gitignore +0 -0
  119. data/spec/data/provider/flickr/flickr_favorites-activity_streams.xml +1040 -0
  120. data/spec/data/provider/flickr/flickr_favorites-raw_rss.xml +557 -0
  121. data/spec/data/provider/flixster/.gitignore +0 -0
  122. data/spec/data/provider/fotolog/.gitignore +0 -0
  123. data/spec/data/provider/friendfeed/.gitignore +0 -0
  124. data/spec/data/provider/friendster/.gitignore +0 -0
  125. data/spec/data/provider/funny_or_die/.gitignore +0 -0
  126. data/spec/data/provider/gamer_dna/.gitignore +0 -0
  127. data/spec/data/provider/gather/.gitignore +0 -0
  128. data/spec/data/provider/generic_feed/.gitignore +0 -0
  129. data/spec/data/provider/goodreads/.gitignore +0 -0
  130. data/spec/data/provider/google_reader/.gitignore +0 -0
  131. data/spec/data/provider/hatena/.gitignore +0 -0
  132. data/spec/data/provider/hi5/.gitignore +0 -0
  133. data/spec/data/provider/hulu/.gitignore +0 -0
  134. data/spec/data/provider/hyves/.gitignore +0 -0
  135. data/spec/data/provider/identica/.gitignore +0 -0
  136. data/spec/data/provider/identica/identica_statuses-raw_feed.xml +465 -0
  137. data/spec/data/provider/ilike/.gitignore +0 -0
  138. data/spec/data/provider/jaiku/.gitignore +0 -0
  139. data/spec/data/provider/joost/.gitignore +0 -0
  140. data/spec/data/provider/lastfm/.gitignore +0 -0
  141. data/spec/data/provider/librarything/.gitignore +0 -0
  142. data/spec/data/provider/livejournal/.gitignore +0 -0
  143. data/spec/data/provider/meneame/.gitignore +0 -0
  144. data/spec/data/provider/metacafe/.gitignore +0 -0
  145. data/spec/data/provider/mixx/.gitignore +0 -0
  146. data/spec/data/provider/moby_picture/.gitignore +0 -0
  147. data/spec/data/provider/multiply/.gitignore +0 -0
  148. data/spec/data/provider/netlog/.gitignore +0 -0
  149. data/spec/data/provider/newsvine/.gitignore +0 -0
  150. data/spec/data/provider/pandora/.gitignore +0 -0
  151. data/spec/data/provider/photobucket/.gitignore +0 -0
  152. data/spec/data/provider/photocase/.gitignore +0 -0
  153. data/spec/data/provider/picasa/.gitignore +0 -0
  154. data/spec/data/provider/plurk/.gitignore +0 -0
  155. data/spec/data/provider/posterous/.gitignore +0 -0
  156. data/spec/data/provider/propeller/.gitignore +0 -0
  157. data/spec/data/provider/qik/.gitignore +0 -0
  158. data/spec/data/provider/qype/.gitignore +0 -0
  159. data/spec/data/provider/raptr/.gitignore +0 -0
  160. data/spec/data/provider/readernaut/.gitignore +0 -0
  161. data/spec/data/provider/reddit/.gitignore +0 -0
  162. data/spec/data/provider/revver/.gitignore +0 -0
  163. data/spec/data/provider/skyrock/.gitignore +0 -0
  164. data/spec/data/provider/slideshare/.gitignore +0 -0
  165. data/spec/data/provider/smotri/.gitignore +0 -0
  166. data/spec/data/provider/smugmug/.gitignore +0 -0
  167. data/spec/data/provider/stumbleupon/.gitignore +0 -0
  168. data/spec/data/provider/tumblr/.gitignore +0 -0
  169. data/spec/data/provider/tumblr/tumblr_posts-raw_feed.xml +150 -0
  170. data/spec/data/provider/twelve_seconds/.gitignore +0 -0
  171. data/spec/data/provider/twine/.gitignore +0 -0
  172. data/spec/data/provider/twitter/.gitignore +0 -0
  173. data/spec/data/provider/twitter/twitter-api_user_timeline-activity_streams.xml +27 -0
  174. data/spec/data/provider/twitter/twitter-api_user_timeline-raw_json.json +1 -0
  175. data/spec/data/provider/twitter/twitter_rss_user_timeline-activity_streams.xml +46 -0
  176. data/spec/data/provider/twitter/twitter_rss_user_timeline-raw_feed.xml +83 -0
  177. data/spec/data/provider/vimeo/.gitignore +0 -0
  178. data/spec/data/provider/visualizeus/.gitignore +0 -0
  179. data/spec/data/provider/wordpress/.gitignore +0 -0
  180. data/spec/data/provider/xanga/.gitignore +0 -0
  181. data/spec/data/provider/yelp/.gitignore +0 -0
  182. data/spec/data/provider/youtube/youtube_videos-activity_streams.xml +629 -0
  183. data/spec/data/provider/youtube/youtube_videos-raw_feed.xml +51 -0
  184. data/spec/data/provider/zooomr/.gitignore +0 -0
  185. data/spec/spec_helper.rb +3 -2
  186. data/spec/support/compare_to_standard_example.rb +17 -0
  187. data/spec/titi_spec.rb +8 -2
  188. data/titi.gemspec +179 -5
  189. metadata +180 -6
  190. data/lib/titi/provider/generic_rss.rb +0 -50
@@ -2,12 +2,12 @@ h1. titi: Agile Monkeying around with Activity Streams
2
2
 
3
3
  Titi is a first stab at a universal ActivityStream interface.
4
4
 
5
- h3. BUGS:
5
+ h3. How you can help
6
6
 
7
- * The XML output isn't activity stream format: needs namespaces, much more
7
+ * Give the coders something to target: a) Pick an API or feed to add. For ideas, choose one not yet implemented from "Supported Feeds" list, below. b) Get a sample of the raw API or feed output (use your own account so noone files a copyright violation bug report). c) create an appropriately-named file, say @spec/data/providers/PROVIDER_NAME/PROVIDER_FEED_NAME-raw_feed.xml@ or @spec/data/providers/PROVIDER_NAME/PROVIDER_FEED_NAME-raw_api.json@ or whatever. d) If that feed is not yet in activity_streams format, use the raw sample to create an example activity_streams output. e) Issue a pull request.
8
+ * Take an API or feed that has example input and output and code its interface.
8
9
 
9
-
10
- h3. Example
10
+ h2. Example
11
11
 
12
12
  Let's define a super-simple twitter user and status model:
13
13
 
@@ -103,6 +103,25 @@ Here's example output. _note: this isn't canonical activity streams format: the
103
103
  </entry>
104
104
  </code></pre>
105
105
 
106
+ h2. Supported Feeds
107
+
108
+ The goal is to cover all the following services. Thanks to "Cliqset":http://feedproxy.cliqset.com/feed/selection and Rob Dolin for the list:
109
+
110
+ <pre><code>
111
+ :social => %w[ AvatarsUnited Bebo Brightkite Friendster Friendfeed GamerDna Gather Hi5 Hyves Identica
112
+ Jaiku Multiply Myspace Netlog Plurk Raptr Skyrock Twitter Facebook LinkedIn Plaxo Xing ],
113
+ :blogging => %w[ Ameba Baidu Blogger Douban Livejournal Posterous Tumblr Wordpress Xanga TypePad MoveableType WlSpaces ],
114
+ :bookmarking => %w[ Delicious Digg Diigo GoogleReader Hatena Meneame Mixx Newsvine Propeller Reddit Stumbleupon Twine ],
115
+ :music => %w[ Blipfm Buzznet Ilike Lastfm Pandora Zooomr Zune ],
116
+ :video => %w[ BuddyTv TwelveSeconds Bliptv Cinchcast DailyMotion FunnyOrDie Hulu Joost Metacafe Qik Revver Vimeo Youtube ],
117
+ :photos => %w[ DeviantArt Flickr Fotolog MobyPicture Photobucket Picasa Photocase Slideshare Smotri Smugmug Visualizeus MetroFlog WlSkyDrive ],
118
+ :reviews => %w[ Blippr Corkd Flixster Goodreads Librarything Qype Readernaut Yelp ],
119
+ :messengers => %w[ AIM WlMessenger ],
120
+ :location => %w[ Gowalla Foursquare Tripit UrbanSpoon Whirl ],
121
+ :gaming => %w[ Zynga Playdom MsgrGames ],
122
+ </code></pre>
123
+
124
+
106
125
  h2. Copyright
107
126
 
108
127
  Copyright (c) 2010 Infochimps, Inc. Available under Apache license: see LICENSE for details.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.5
1
+ 0.0.6
@@ -1,18 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'rubygems'
3
- require 'restclient'
4
- require 'json'
5
- require 'active_support'
6
-
7
3
  TITI_DIR = File.dirname(File.expand_path(__FILE__+'/..')) unless defined?(TITI_DIR)
8
4
  $: << TITI_DIR+'/lib' unless $:.include?(TITI_DIR+'/lib')
9
-
10
- require 'titi'
5
+ require 'titi' ; include Titi::Provider
11
6
  require 'titi/provider/twitter'
12
- include Titi::Provider
13
-
14
- tweet = Twitter::Status.get(12233609555)
15
- entry = tweet.to_activity_stream_entry
16
7
 
17
- p tweet.to_hash
18
- puts entry.to_xml
8
+ tweet = Twitter::Status.fetch_status(12233609555)
9
+ tw_feed = tweet.to_activity_stream
10
+ puts tw_feed.to_xml
@@ -1,4 +1,10 @@
1
+ require 'restclient'
2
+ require 'json'
3
+ require 'wukong'
4
+ require 'erubis'
5
+
1
6
  module Titi
2
7
  autoload :Provider, 'titi/provider'
3
8
  autoload :Adaptor, 'titi/adaptor'
9
+ autoload :Fetcher, 'titi/fetcher'
4
10
  end
@@ -0,0 +1,5 @@
1
+ module Titi
2
+ module Fetcher
3
+ autoload :Json, 'titi/fetcher/json'
4
+ end
5
+ end
@@ -0,0 +1,32 @@
1
+ module Titi::Fetcher
2
+ module Json
3
+ module ClassMethods
4
+
5
+ def parse raw_json_str
6
+ begin
7
+ return JSON.load(raw_json_str)
8
+ rescue StandardError => e
9
+ warn e
10
+ return { }
11
+ end
12
+ end
13
+
14
+ # Call the twitter API and fetch tweet with given ID
15
+ #
16
+ # @example
17
+ # tweet = Status.get(12233609555)
18
+ # tweet.text
19
+ # #=> "THANK GOODNESS THE LIBRARY OF CONGRESS HAS UNDERSTOOD THE IMPORTANCE OF MY TWEETS what do you mean others are getting in too"
20
+ #
21
+ def get url
22
+ parse RestClient.get(url).to_s
23
+ end
24
+
25
+ def from_file filename
26
+ parse File.open(filename)
27
+ end
28
+ end
29
+ # Standard hack to add class methods
30
+ def self.included(base) base.class_eval{ extend ClassMethods } ; end
31
+ end
32
+ end
@@ -1,4 +1,3 @@
1
- require 'wukong'
2
1
  module Titi
3
2
  module Provider
4
3
  autoload :ActivityStreams, 'titi/provider/activity_streams'
@@ -16,25 +15,3 @@ module Titi
16
15
  # autoload :WordPress , 'titi/provider/word_press'
17
16
  end
18
17
  end
19
-
20
- # # from Rob Dolin, a list:
21
- # {
22
- # :text_status => %w[ Twitter StatusNet Plurk AIM WlMessenger ],
23
- # :location => %w[ Gowalla Foursquare Tripit Yelp Qype UrbanSpoon Brightkite Whirl ],
24
- # :social => %w[ Facebook MySpace LinkedIn Xing Plaxo ],
25
- # :music => %w[ LastFm Pandora Zune iLike ],
26
- # :bookmarking => %w[ Digg StumbleUpon Delicious Facebook ],
27
- # :video => %w[ YouTube DailyMotion Hulu BuddyTv SkyDrive ],
28
- # :gaming => %w[ Zynga Playdom MsgrGames ],
29
- # :photos => %w[ Flickr Photobucket MetroFlog Fotolog Picasa WlSkyDrive ],
30
- # :blogging => %w[ Blogger WordPress TypePad MySpace MoveableType WlSpaces ],
31
- # }
32
- #
33
- # # See also: http://feedproxy.cliqset.com/feed/selection
34
- # {
35
- # Social => %w[ AvatarsUnited Bebo BrightKite Friendster FriendFeed GamerDNA Gather hi5 Hyves Identica Jaiku Multiply Netlog Plurk Raptr Skyrock Twitter ],
36
- # Blogging => %w[ Ameba Baidu Blogger CustomFeed Douban LiveJournal Posterous Tumblr WordPress Xanga ],
37
- # Bookmarking => %w[ Delicious Digg Diigo GoogleReader Hatena Meneame Mixx Newsvine Propeller Reddit StumbleUpon Twine ],
38
- # Media => %w[ 12seconds BlipFm BlipTv Buzznet Cinchcast Dailymotion DeviantArt Flickr Fotolog FunnyOrDie Hulu iLike Joost LastFm MetaCafe MobyPicture Pandora Photobucket Photocase Picasa Qik Revver SlideShare Smotri SmugMug VisualizeUs Vimeo YouTube Zooomr ],
39
- # Reviews => %w[ Blippr Corkd Flixster Goodreads LibraryThing Qype Readernaut Yelp ],
40
- # }
@@ -1,141 +1,12 @@
1
- module Titi
2
-
3
- module Provider
4
- #
5
- module ActivityStreams
6
- # Some methods common to all ActivityStreams classes
7
- module Common
8
- def to_hash *args
9
- hsh = super(*args)
10
- hsh.each do |attr, val|
11
- hsh[attr] = val.to_hash if val.respond_to?(:to_hash)
12
- end
13
- hsh
14
- end
15
-
16
- def to_xml *args
17
- hsh = self.to_hash
18
- hsh.to_xml :root => self.class.to_s.underscore.gsub(%r{.*/},'')
19
- end
20
-
21
- def has_thingy thingy, *args, &block
22
- thingy_klass = ('ActivityStreams::'+thingy.to_s.classify).constantize
23
- thingy_setter = "#{thingy}="
24
- p [thingy, thingy_klass, thingy_setter]
25
- self.send(thingy_setter, thingy_klass.new) unless self.send(thingy)
26
- self.send(thingy).adapt *args, &block
27
- self.send(thingy)
28
- end
29
-
30
- def method_missing meth, *args, &block
31
- if (meth.to_s =~ /has_(\w+)/) && (self.respond_to?("#{$1}="))
32
- has_thingy $1, *args, &block
33
- else
34
- super
35
- end
36
- end
37
- end
38
-
39
- class ActivityStreamsStruct < ActivityStreamsStruct
40
- def self.new *args, &block
41
- super
42
- include Titi::Adaptor
43
- include Titi::Provider::ActivityStreams::Common
44
- end
45
- end
46
-
47
- Feed = ActivityStreamsStruct.new(
48
- :entry
49
- )
50
- Feed.class_eval do
51
- def adapt thingys
52
- self.entry = thingys.map do |thingy|
53
- thingy.to_activity_stream_entry
54
- end
55
- end
56
- end
57
-
58
- # An ActivityStream entry
59
- # http://activitystrea.ms/spec/1.0/atom-activity-01.html#activityentries
60
- Entry = ActivityStreamsStruct.new(
61
- :id, # ???
62
- :title, # title
63
- :content, # content
64
- :link, # link {"href"=>"http://x.myspacecdn.com/modules/common/static/img/photo.gif", "rel"=>"icon", "type"=>"image/gif"}
65
- :published, # date published
66
- :updated, # date updated
67
- #
68
- :category, # type of entry
69
- :activity_verb, # action it implies:
70
- :sync, # sync
71
- :rank, # rank
72
- #
73
- :actor, # actor
74
- :author, # author {"name"=>["misterflip"], "uri"=>["http://profile.myspace.com/index.cfm?fuseaction=user.viewprofile&friendid=24601"]}
75
- :mood, #
76
- :source,
77
- :obj, # object
78
- :target # target
79
- )
80
- Entry.class_eval do
81
- def published= date_time
82
- self[:published] = DateTime.parse(date_time) rescue nil
83
- end
84
- def updated= date_time
85
- self[:updated] = DateTime.parse(date_time) rescue nil
86
- end
87
- end
88
-
89
- # <link href="http://twitter.com/banksean/statuses/12244282580"
90
- # type="text/xhtml" rel="via" title="Just saw a @cliqset #salmon @-mention interop demo by @jpanzer. Very neat stuff!">
91
- # </link>
92
-
93
- Link = ActivityStreamsStruct.new(
94
- :href,
95
- :title,
96
- :rel,
97
- :type
98
- )
99
- Link.class_eval do
100
- end
101
-
102
- Address = ActivityStreamsStruct.new(
103
- :country,
104
- :locality,
105
- :postalCode,
106
- #
107
- :xml_keys # for debugging, capture the keys from the raw XML hash
108
- )
109
- Address.class_eval do
110
- end
111
-
112
- # ActivityStream author
113
- # http://activitystrea.ms/spec/1.0/atom-activity-01.html#activityactor
114
- Actor = ActivityStreamsStruct.new(
115
- :name,
116
- :uri
117
- )
118
- Actor.class_eval do
119
- end
120
- Author = Actor
121
-
122
- # ActivityStream object.
123
- # We can't call them 'Object' (ruby has a class like that already :)
124
- # http://activitystrea.ms/spec/1.0/atom-activity-01.html#activityobjectelement
125
- Obj = ActivityStreamsStruct.new(
126
- :id,
127
- :title,
128
- :content,
129
- :link,
130
- :published,
131
- :updated,
132
- #
133
- :author,
134
- :object_type, # video, post, file
135
- :vevent
136
- )
137
- Obj.class_eval do
138
- end
139
- end
1
+ module Titi::Provider
2
+ module ActivityStreams
3
+ autoload :ActivityStreamsStruct, 'titi/provider/activity_streams/activity_streams_struct'
4
+ autoload :Actor, 'titi/provider/activity_streams/actor'
5
+ autoload :Author, 'titi/provider/activity_streams/actor'
6
+ autoload :Address, 'titi/provider/activity_streams/address'
7
+ autoload :Entry, 'titi/provider/activity_streams/entry'
8
+ autoload :Feed, 'titi/provider/activity_streams/feed'
9
+ autoload :Link, 'titi/provider/activity_streams/link'
10
+ autoload :Obj, 'titi/provider/activity_streams/obj'
140
11
  end
141
12
  end
@@ -0,0 +1,46 @@
1
+ module Titi::Provider::ActivityStreams
2
+ class ActivityStreamsStruct < Struct
3
+ include Titi::Adaptor
4
+
5
+ # Merge given attributes into the hash
6
+ def attributes= hsh
7
+ conv_hsh = {}
8
+ hsh.each do |k,v|
9
+ k = k.to_s.gsub(/:/,'_') if k =~ /:/
10
+ conv_hsh[k] = v
11
+ end
12
+ super hsh
13
+ end
14
+
15
+ # expand to hash, and expand all hash values to hash
16
+ def to_hash *args
17
+ hsh = super(*args)
18
+ hsh.each do |attr, val|
19
+ hsh[attr] = val.to_hash if val.respond_to?(:to_hash)
20
+ end
21
+ hsh
22
+ end
23
+
24
+ # def to_xml *args
25
+ # hsh = self.to_hash
26
+ # hsh.to_xml :root => self.class.to_s.underscore.gsub(%r{.*/},'')
27
+ # end
28
+
29
+ # Use method_missing to dispatch the has_[whatever] setters
30
+ def method_missing meth, *args, &block
31
+ if (meth.to_s =~ /has_(\w+)/) && (self.respond_to?("#{$1}="))
32
+ has_thingy $1, *args, &block
33
+ else
34
+ super
35
+ end
36
+ end
37
+
38
+ def has_thingy thingy, *args, &block
39
+ thingy_klass = ('Titi::Provider::ActivityStreams::'+thingy.to_s.camelize).constantize
40
+ thingy_setter = "#{thingy}="
41
+ self.send(thingy_setter, thingy_klass.new) unless self.send(thingy)
42
+ self.send(thingy).adapt *args, &block
43
+ self.send(thingy)
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,11 @@
1
+ module Titi::Provider::ActivityStreams
2
+ # ActivityStream author
3
+ # http://activitystrea.ms/spec/1.0/atom-activity-01.html#activityactor
4
+ Actor = ActivityStreamsStruct.new(
5
+ :name,
6
+ :uri
7
+ )
8
+ Actor.class_eval do
9
+ end
10
+ Author = Actor
11
+ end
@@ -0,0 +1,11 @@
1
+ module Titi::Provider::ActivityStreams
2
+ Address = ActivityStreamsStruct.new(
3
+ :country,
4
+ :locality,
5
+ :postalCode,
6
+ #
7
+ :xml_keys # for debugging, capture the keys from the raw XML hash
8
+ )
9
+ Address.class_eval do
10
+ end
11
+ end
@@ -0,0 +1,38 @@
1
+ module Titi::Provider::ActivityStreams
2
+
3
+ # An ActivityStream entry
4
+ # http://activitystrea.ms/spec/1.0/atom-activity-01.html#activityentries
5
+ Entry = ActivityStreamsStruct.new(
6
+ :id, # ???
7
+ :title, # title
8
+ :content, # content
9
+ :link_alt, # link {"href"=>"http://x.myspacecdn.com/modules/common/static/img/photo.gif", "rel"=>"icon", "type"=>"image/gif"}
10
+ :link_enclosure, # link {"href"=>"http://x.myspacecdn.com/modules/common/static/img/photo.gif", "rel"=>"icon", "type"=>"image/gif"}
11
+ :link_preview, # link {"href"=>"http://x.myspacecdn.com/modules/common/static/img/photo.gif", "rel"=>"icon", "type"=>"image/gif"}
12
+ :link_icon, # link {"href"=>"http://x.myspacecdn.com/modules/common/static/img/photo.gif", "rel"=>"icon", "type"=>"image/gif"}
13
+ :link_related, # link {"href"=>"http://x.myspacecdn.com/modules/common/static/img/photo.gif", "rel"=>"icon", "type"=>"image/gif"}
14
+
15
+ :published, # date published
16
+ :updated, # date updated
17
+ #
18
+ :category, # type of entry
19
+ :activity_verb, # action it implies:
20
+ :sync, # sync
21
+ :rank, # rank
22
+ #
23
+ :actor, # actor
24
+ :author, # author {"name"=>["misterflip"], "uri"=>["http://profile.myspace.com/index.cfm?fuseaction=user.viewprofile&friendid=24601"]}
25
+ :mood, #
26
+ :source,
27
+ :obj, # object
28
+ :target # target
29
+ )
30
+ Entry.class_eval do
31
+ def published= date_time
32
+ self[:published] = DateTime.parse(date_time) rescue nil
33
+ end
34
+ def updated= date_time
35
+ self[:updated] = DateTime.parse(date_time) rescue nil
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,25 @@
1
+ module Titi::Provider::ActivityStreams
2
+ Feed = ActivityStreamsStruct.new(
3
+ :entry
4
+ )
5
+ Feed.class_eval do
6
+ # Location of the .erb file for rendering pretty activity streams XML
7
+ ACTIVITY_STREAMS_TEMPLATE = File.join(File.dirname(__FILE__)+'/feed.xml.erb')
8
+
9
+ def entries
10
+ [entry].flatten
11
+ end
12
+
13
+ def self.activity_streams_template
14
+ @activity_streams_template ||= File.read(ACTIVITY_STREAMS_TEMPLATE)
15
+ end
16
+
17
+ def self.activity_streams_renderer
18
+ @activity_streams_renderer ||= Erubis::Eruby.new(activity_streams_template)
19
+ end
20
+
21
+ def to_xml
22
+ self.class.activity_streams_renderer.result(:feed => self)
23
+ end
24
+ end
25
+ end
@@ -1,27 +1,29 @@
1
1
  <feed>
2
+ <%- feed.entries.each do |entry| %>
2
3
  <entry>
3
4
  <title><%= entry.title %></title>
4
5
  <content type="html"><%= entry.content %></content>
5
6
  <id><%= entry.id %></id>
6
7
  <published><%= entry.published %></published>
7
8
  <updated ><%= entry.updated %></updated>
8
- <link type="text/html" rel="alternate" href="<%= entry.alt_link %>"/>
9
- <link type="image/pjpeg" rel="image" href="<%= entry.img_link %>"/>
9
+ <link type="text/html" rel="alternate" href="<%= entry.link_alt %>"/>
10
+ <link type="image/pjpeg" rel="icon" href="<%= entry.link_icon %>"/>
10
11
  <author>
11
12
  <name><%= entry.author.name %></name>
12
- <uri><%= entry.author.url %></uri>
13
+ <uri><%= entry.author.uri %></uri>
13
14
  </author>
14
- <activity:verb><%= entry.verb %></activity:verb>
15
+ <activity:verb><%= entry.activity_verb %></activity:verb>
15
16
  <activity:object>
16
- <id><%= entry.object.id %></id>
17
- <title><%= entry.object.title %></title>
18
- <link type="text/html" rel="alternate" href="<%= entry.object.alt_link %>"/>
19
- <published><%= entry.object.published %></published>
20
- <updated ><%= entry.object.updated %></updated>
17
+ <id><%= entry.obj.id %></id>
18
+ <title><%= entry.obj.title %></title>
19
+ <link type="text/html" rel="alternate" href="<%= entry.obj.link_alt %>"/>
20
+ <published><%= entry.obj.published %></published>
21
+ <updated ><%= entry.obj.updated %></updated>
21
22
  <author>
22
- <name><%= entry.object.author.name %></name>
23
- <uri ><%= entry.object.author.url %></uri>
23
+ <name><%= entry.obj.author.name %></name>
24
+ <uri ><%= entry.obj.author.uri %></uri>
24
25
  </author>
25
26
  </activity:object>
26
27
  </entry>
28
+ <%- end %>
27
29
  </feed>