kete-feedzirra 0.0.8.1 → 0.0.16.1
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/README.textile +11 -2
- data/Rakefile +3 -0
- data/lib/feedzirra.rb +10 -10
- data/lib/feedzirra/feed.rb +45 -42
- data/lib/feedzirra/parser/atom.rb +47 -0
- data/lib/feedzirra/parser/atom_entry.rb +51 -0
- data/lib/feedzirra/parser/atom_feed_burner.rb +27 -0
- data/lib/feedzirra/parser/atom_feed_burner_entry.rb +35 -0
- data/lib/feedzirra/parser/itunes_rss.rb +50 -0
- data/lib/feedzirra/parser/itunes_rss_item.rb +31 -0
- data/lib/feedzirra/parser/itunes_rss_owner.rb +12 -0
- data/lib/feedzirra/parser/rss.rb +40 -0
- data/lib/feedzirra/parser/rss_entry.rb +55 -0
- data/spec/feedzirra/feed_spec.rb +30 -27
- data/spec/feedzirra/feed_utilities_spec.rb +9 -9
- data/spec/feedzirra/{atom_entry_spec.rb → parser/atom_entry_spec.rb} +7 -3
- data/spec/feedzirra/{atom_feed_burner_entry_spec.rb → parser/atom_feed_burner_entry_spec.rb} +4 -4
- data/spec/feedzirra/{atom_feed_burner_spec.rb → parser/atom_feed_burner_spec.rb} +6 -6
- data/spec/feedzirra/{atom_spec.rb → parser/atom_spec.rb} +16 -8
- data/spec/feedzirra/{itunes_rss_item_spec.rb → parser/itunes_rss_item_spec.rb} +3 -3
- data/spec/feedzirra/{itunes_rss_owner_spec.rb → parser/itunes_rss_owner_spec.rb} +3 -3
- data/spec/feedzirra/{itunes_rss_spec.rb → parser/itunes_rss_spec.rb} +5 -5
- data/spec/feedzirra/{rss_entry_spec.rb → parser/rss_entry_spec.rb} +14 -14
- data/spec/feedzirra/{rss_spec.rb → parser/rss_spec.rb} +17 -18
- metadata +22 -21
- data/lib/feedzirra/atom.rb +0 -35
- data/lib/feedzirra/atom_entry.rb +0 -41
- data/lib/feedzirra/atom_feed_burner.rb +0 -22
- data/lib/feedzirra/atom_feed_burner_entry.rb +0 -30
- data/lib/feedzirra/itunes_rss.rb +0 -46
- data/lib/feedzirra/itunes_rss_item.rb +0 -28
- data/lib/feedzirra/itunes_rss_owner.rb +0 -8
- data/lib/feedzirra/rss.rb +0 -36
- data/lib/feedzirra/rss_entry.rb +0 -48
    
        data/README.textile
    CHANGED
    
    | @@ -23,10 +23,12 @@ The final feature of Feedzirra is the ability to define custom parsing classes. | |
| 23 23 | 
             
            h2. Installation
         | 
| 24 24 |  | 
| 25 25 | 
             
            For now Feedzirra exists only on github. It also has a few gem requirements that are only on github. Before you start you need to have "libcurl":http://curl.haxx.se/ and "libxml":http://xmlsoft.org/ installed. If you're on Leopard you have both. Otherwise, you'll need to grab them. Once you've got those libraries, these are the gems that get used: nokogiri, pauldix-sax-machine, taf2-curb (note that this is a fork that lives on github and not the Ruby Forge version of curb), and pauldix-feedzirra. The feedzirra gemspec has all the dependencies so you should be able to get up and running with the standard github gem install routine:
         | 
| 26 | 
            +
             | 
| 26 27 | 
             
            <pre>
         | 
| 27 28 | 
             
            gem sources -a http://gems.github.com # if you haven't already
         | 
| 28 29 | 
             
            gem install pauldix-feedzirra
         | 
| 29 30 | 
             
            </pre>
         | 
| 31 | 
            +
             | 
| 30 32 | 
             
            <b>NOTE:</b>Some people have been reporting a few issues related to installation. First, the Ruby Forge version of curb is not what you want. It will not work. Nor will the curl-multi gem that lives on Ruby Forge. You have to get the "taf2-curb":http://github.com/taf2/curb/tree/master fork installed.
         | 
| 31 33 |  | 
| 32 34 | 
             
            If you see this error when doing a require: 
         | 
| @@ -93,7 +95,7 @@ updated_feed.new_entries  # a collection of the entry objects that are newer tha | |
| 93 95 |  | 
| 94 96 | 
             
            # fetching multiple feeds
         | 
| 95 97 | 
             
            feed_urls = ["http://feeds.feedburner.com/PaulDixExplainsNothing", "http://feeds.feedburner.com/trottercashion"]
         | 
| 96 | 
            -
            feeds = Feedzirra::Feed.fetch_and_parse( | 
| 98 | 
            +
            feeds = Feedzirra::Feed.fetch_and_parse(feed_urls)
         | 
| 97 99 |  | 
| 98 100 | 
             
            # feeds is now a hash with the feed_urls as keys and the parsed feed objects as values. If an error was thrown
         | 
| 99 101 | 
             
            # there will be a Fixnum of the http response code instead of a feed object
         | 
| @@ -116,6 +118,12 @@ Feedzirra::Feed.add_common_feed_entry_element("wfw:commentRss", :as => :comment_ | |
| 116 118 | 
             
            # AtomEntry classes. Now you can access those in an atom feed:
         | 
| 117 119 | 
             
            Feedzirra::Feed.parse(some_atom_xml).entries.first.comment_rss_ # => wfw:commentRss is now parsed!
         | 
| 118 120 |  | 
| 121 | 
            +
             | 
| 122 | 
            +
            # You can also define your own parsers and add them to the ones Feedzirra knows about. Here's an example that adds 
         | 
| 123 | 
            +
            # ITunesRSS parsing. It's included in the library, but not part of Feedzirra by default because some of the field names 
         | 
| 124 | 
            +
            # differ from other classes, thus breaking normalization.
         | 
| 125 | 
            +
            Feedzirra::Feed.add_feed_class(ITunesRSS) # now all feeds will be checked to see if they match ITunesRSS before others
         | 
| 126 | 
            +
             | 
| 119 127 | 
             
            # You can also access http basic auth feeds. Unfortunately, you can't get to these inside of a bulk get of a bunch of feeds.
         | 
| 120 128 | 
             
            # You'll have to do it on its own like so:
         | 
| 121 129 | 
             
            Feedzirra::Feed.fetch_and_parse(some_url, :http_authentication => ["myusername", "mypassword"])
         | 
| @@ -151,7 +159,8 @@ This thing needs to hammer on many different feeds in the wild. I'm sure there w | |
| 151 159 | 
             
            Here are some more specific TODOs.
         | 
| 152 160 | 
             
            * Fix the iTunes parser so things are normalized again
         | 
| 153 161 | 
             
            * Fix the Zlib deflate error
         | 
| 154 | 
            -
            *  | 
| 162 | 
            +
            * Fix this error: http://github.com/inbox/70508
         | 
| 163 | 
            +
            * Convert to use Typhoeus instead of taf2-curb
         | 
| 155 164 | 
             
            * Make the entries parse all link fields
         | 
| 156 165 | 
             
            * Make a feedzirra-rails gem to integrate feedzirra seamlessly with Rails and ActiveRecord.
         | 
| 157 166 | 
             
            * Create a super sweet DSL for defining new parsers.
         | 
    
        data/Rakefile
    CHANGED
    
    
    
        data/lib/feedzirra.rb
    CHANGED
    
    | @@ -18,17 +18,17 @@ require 'feedzirra/feed_utilities' | |
| 18 18 | 
             
            require 'feedzirra/feed_entry_utilities'
         | 
| 19 19 | 
             
            require 'feedzirra/feed'
         | 
| 20 20 |  | 
| 21 | 
            -
            require 'feedzirra/rss_entry'
         | 
| 22 | 
            -
            require 'feedzirra/itunes_rss_owner'
         | 
| 23 | 
            -
            require 'feedzirra/itunes_rss_item'
         | 
| 24 | 
            -
            require 'feedzirra/atom_entry'
         | 
| 25 | 
            -
            require 'feedzirra/atom_feed_burner_entry'
         | 
| 21 | 
            +
            require 'feedzirra/parser/rss_entry'
         | 
| 22 | 
            +
            require 'feedzirra/parser/itunes_rss_owner'
         | 
| 23 | 
            +
            require 'feedzirra/parser/itunes_rss_item'
         | 
| 24 | 
            +
            require 'feedzirra/parser/atom_entry'
         | 
| 25 | 
            +
            require 'feedzirra/parser/atom_feed_burner_entry'
         | 
| 26 26 |  | 
| 27 | 
            -
            require 'feedzirra/rss'
         | 
| 28 | 
            -
            require 'feedzirra/itunes_rss'
         | 
| 29 | 
            -
            require 'feedzirra/atom'
         | 
| 30 | 
            -
            require 'feedzirra/atom_feed_burner'
         | 
| 27 | 
            +
            require 'feedzirra/parser/rss'
         | 
| 28 | 
            +
            require 'feedzirra/parser/itunes_rss'
         | 
| 29 | 
            +
            require 'feedzirra/parser/atom'
         | 
| 30 | 
            +
            require 'feedzirra/parser/atom_feed_burner'
         | 
| 31 31 |  | 
| 32 32 | 
             
            module Feedzirra
         | 
| 33 | 
            -
              VERSION = "0.0. | 
| 33 | 
            +
              VERSION = "0.0.16"
         | 
| 34 34 | 
             
            end
         | 
    
        data/lib/feedzirra/feed.rb
    CHANGED
    
    | @@ -27,7 +27,7 @@ module Feedzirra | |
| 27 27 | 
             
                # === Returns
         | 
| 28 28 | 
             
                # The class name of the parser that can handle the XML.
         | 
| 29 29 | 
             
                def self.determine_feed_parser_for_xml(xml)
         | 
| 30 | 
            -
                  start_of_doc = xml.slice(0,  | 
| 30 | 
            +
                  start_of_doc = xml.slice(0, 2000)
         | 
| 31 31 | 
             
                  feed_classes.detect {|klass| klass.able_to_parse?(start_of_doc)}
         | 
| 32 32 | 
             
                end
         | 
| 33 33 |  | 
| @@ -46,7 +46,7 @@ module Feedzirra | |
| 46 46 | 
             
                # === Returns
         | 
| 47 47 | 
             
                # A array of class names.
         | 
| 48 48 | 
             
                def self.feed_classes
         | 
| 49 | 
            -
                  @feed_classes ||= [ | 
| 49 | 
            +
                  @feed_classes ||= [Feedzirra::Parser::RSS, Feedzirra::Parser::AtomFeedBurner, Feedzirra::Parser::Atom]
         | 
| 50 50 | 
             
                end
         | 
| 51 51 |  | 
| 52 52 | 
             
                # Makes all entry types look for the passed in element to parse. This is actually just a call to 
         | 
| @@ -58,25 +58,11 @@ module Feedzirra | |
| 58 58 | 
             
                def self.add_common_feed_entry_element(element_tag, options = {})
         | 
| 59 59 | 
             
                  # need to think of a better way to do this. will break for people who want this behavior
         | 
| 60 60 | 
             
                  # across their added classes
         | 
| 61 | 
            -
                   | 
| 61 | 
            +
                  feed_classes.map{|k| eval("#{k}Entry") }.each do |klass|
         | 
| 62 62 | 
             
                    klass.send(:element, element_tag, options)
         | 
| 63 63 | 
             
                  end
         | 
| 64 64 | 
             
                end
         | 
| 65 65 |  | 
| 66 | 
            -
                # Makes all entry types look for the passed in elements to parse. This is actually just a call to 
         | 
| 67 | 
            -
                # elements (a SAXMachine call) in the class
         | 
| 68 | 
            -
                #
         | 
| 69 | 
            -
                # === Parameters
         | 
| 70 | 
            -
                # [element_tag<String>]
         | 
| 71 | 
            -
                # [options<Hash>] Valid keys are same as with SAXMachine
         | 
| 72 | 
            -
                def self.add_common_feed_entry_elements(element_tag, options = {})
         | 
| 73 | 
            -
                  # need to think of a better way to do this. will break for people who want this behavior
         | 
| 74 | 
            -
                  # across their added classes
         | 
| 75 | 
            -
                  [RSSEntry, AtomFeedBurnerEntry, AtomEntry].each do |klass|
         | 
| 76 | 
            -
                    klass.send(:elements, element_tag, options)
         | 
| 77 | 
            -
                  end
         | 
| 78 | 
            -
                end
         | 
| 79 | 
            -
             | 
| 80 66 | 
             
                # Fetches and returns the raw XML for each URL provided.
         | 
| 81 67 | 
             
                #
         | 
| 82 68 | 
             
                # === Parameters
         | 
| @@ -100,9 +86,12 @@ module Feedzirra | |
| 100 86 | 
             
                      curl.headers["User-Agent"]        = (options[:user_agent] || USER_AGENT)
         | 
| 101 87 | 
             
                      curl.headers["If-Modified-Since"] = options[:if_modified_since].httpdate if options.has_key?(:if_modified_since)
         | 
| 102 88 | 
             
                      curl.headers["If-None-Match"]     = options[:if_none_match] if options.has_key?(:if_none_match)
         | 
| 103 | 
            -
                      curl.headers["Accept-encoding"]   = 'gzip, deflate'
         | 
| 89 | 
            +
                      curl.headers["Accept-encoding"]   = 'gzip, deflate' if options.has_key?(:compress)
         | 
| 104 90 | 
             
                      curl.follow_location = true
         | 
| 105 91 | 
             
                      curl.userpwd = options[:http_authentication].join(':') if options.has_key?(:http_authentication)
         | 
| 92 | 
            +
                      
         | 
| 93 | 
            +
                      curl.max_redirects = options[:max_redirects] if options[:max_redirects]
         | 
| 94 | 
            +
                      curl.timeout = options[:timeout] if options[:timeout]
         | 
| 106 95 |  | 
| 107 96 | 
             
                      curl.on_success do |c|
         | 
| 108 97 | 
             
                        responses[url] = decode_content(c)
         | 
| @@ -115,7 +104,7 @@ module Feedzirra | |
| 115 104 | 
             
                  end
         | 
| 116 105 |  | 
| 117 106 | 
             
                  multi.perform
         | 
| 118 | 
            -
                   | 
| 107 | 
            +
                  urls.is_a?(String) ? responses.values.first : responses
         | 
| 119 108 | 
             
                end
         | 
| 120 109 |  | 
| 121 110 | 
             
                # Fetches and returns the parsed XML for each URL provided.
         | 
| @@ -123,11 +112,11 @@ module Feedzirra | |
| 123 112 | 
             
                # === Parameters
         | 
| 124 113 | 
             
                # [urls<String> or <Array>] A single feed URL, or an array of feed URLs.
         | 
| 125 114 | 
             
                # [options<Hash>] Valid keys for this argument as as followed:
         | 
| 126 | 
            -
                # | 
| 127 | 
            -
                # | 
| 128 | 
            -
                # | 
| 129 | 
            -
                # | 
| 130 | 
            -
                # | 
| 115 | 
            +
                # * :user_agent - String that overrides the default user agent.
         | 
| 116 | 
            +
                # * :if_modified_since - Time object representing when the feed was last updated.
         | 
| 117 | 
            +
                # * :if_none_match - String, an etag for the request that was stored previously.
         | 
| 118 | 
            +
                # * :on_success - Block that gets executed after a successful request.
         | 
| 119 | 
            +
                # * :on_failure - Block that gets executed after a failed request.
         | 
| 131 120 | 
             
                # === Returns
         | 
| 132 121 | 
             
                # A Feed object if a single URL is passed.
         | 
| 133 122 | 
             
                #
         | 
| @@ -137,12 +126,12 @@ module Feedzirra | |
| 137 126 | 
             
                  multi = Curl::Multi.new
         | 
| 138 127 | 
             
                  responses = {}
         | 
| 139 128 |  | 
| 140 | 
            -
                  # I broke these down so I would only try to do 30 simultaneously because | 
| 129 | 
            +
                  # I broke these down so I would only try to do 30 simultaneously because
         | 
| 141 130 | 
             
                  # I was getting weird errors when doing a lot. As one finishes it pops another off the queue.
         | 
| 142 131 | 
             
                  url_queue.slice!(0, 30).each do |url|
         | 
| 143 132 | 
             
                    add_url_to_multi(multi, url, url_queue, responses, options)
         | 
| 144 133 | 
             
                  end
         | 
| 145 | 
            -
             | 
| 134 | 
            +
             
         | 
| 146 135 | 
             
                  multi.perform
         | 
| 147 136 | 
             
                  return urls.is_a?(String) ? responses.values.first : responses
         | 
| 148 137 | 
             
                end
         | 
| @@ -194,7 +183,7 @@ module Feedzirra | |
| 194 183 | 
             
                  end
         | 
| 195 184 |  | 
| 196 185 | 
             
                  multi.perform
         | 
| 197 | 
            -
                   | 
| 186 | 
            +
                  responses.size == 1 ? responses.values.first : responses.values
         | 
| 198 187 | 
             
                end
         | 
| 199 188 |  | 
| 200 189 | 
             
                # An abstraction for adding a feed by URL to the passed Curb::multi stack.
         | 
| @@ -216,9 +205,12 @@ module Feedzirra | |
| 216 205 | 
             
                    curl.headers["User-Agent"]        = (options[:user_agent] || USER_AGENT)
         | 
| 217 206 | 
             
                    curl.headers["If-Modified-Since"] = options[:if_modified_since].httpdate if options.has_key?(:if_modified_since)
         | 
| 218 207 | 
             
                    curl.headers["If-None-Match"]     = options[:if_none_match] if options.has_key?(:if_none_match)
         | 
| 219 | 
            -
                    curl.headers["Accept-encoding"]   = 'gzip, deflate'
         | 
| 208 | 
            +
                    curl.headers["Accept-encoding"]   = 'gzip, deflate' if options.has_key?(:compress)
         | 
| 220 209 | 
             
                    curl.follow_location = true
         | 
| 221 210 | 
             
                    curl.userpwd = options[:http_authentication].join(':') if options.has_key?(:http_authentication)
         | 
| 211 | 
            +
             | 
| 212 | 
            +
                    curl.max_redirects = options[:max_redirects] if options[:max_redirects]
         | 
| 213 | 
            +
                    curl.timeout = options[:timeout] if options[:timeout]
         | 
| 222 214 |  | 
| 223 215 | 
             
                    curl.on_success do |c|
         | 
| 224 216 | 
             
                      add_url_to_multi(multi, url_queue.shift, url_queue, responses, options) unless url_queue.empty?
         | 
| @@ -226,12 +218,16 @@ module Feedzirra | |
| 226 218 | 
             
                      klass = determine_feed_parser_for_xml(xml)
         | 
| 227 219 |  | 
| 228 220 | 
             
                      if klass
         | 
| 229 | 
            -
                         | 
| 230 | 
            -
             | 
| 231 | 
            -
             | 
| 232 | 
            -
             | 
| 233 | 
            -
             | 
| 234 | 
            -
             | 
| 221 | 
            +
                        begin
         | 
| 222 | 
            +
                          feed = klass.parse(xml)
         | 
| 223 | 
            +
                          feed.feed_url = c.last_effective_url
         | 
| 224 | 
            +
                          feed.etag = etag_from_header(c.header_str)
         | 
| 225 | 
            +
                          feed.last_modified = last_modified_from_header(c.header_str)
         | 
| 226 | 
            +
                          responses[url] = feed
         | 
| 227 | 
            +
                          options[:on_success].call(url, feed) if options.has_key?(:on_success)
         | 
| 228 | 
            +
                        rescue Exception => e
         | 
| 229 | 
            +
                          options[:on_failure].call(url, c.response_code, c.header_str, c.body_str) if options.has_key?(:on_failure)
         | 
| 230 | 
            +
                        end
         | 
| 235 231 | 
             
                      else
         | 
| 236 232 | 
             
                        # puts "Error determining parser for #{url} - #{c.last_effective_url}"
         | 
| 237 233 | 
             
                        # raise NoParserAvailable.new("no valid parser for content.") (this would unfirtunately fail the whole 'multi', so it's not really useable)
         | 
| @@ -270,15 +266,22 @@ module Feedzirra | |
| 270 266 | 
             
                    curl.userpwd = options[:http_authentication].join(':') if options.has_key?(:http_authentication)
         | 
| 271 267 | 
             
                    curl.follow_location = true
         | 
| 272 268 |  | 
| 269 | 
            +
                    curl.max_redirects = options[:max_redirects] if options[:max_redirects]
         | 
| 270 | 
            +
                    curl.timeout = options[:timeout] if options[:timeout]
         | 
| 271 | 
            +
             | 
| 273 272 | 
             
                    curl.on_success do |c|
         | 
| 274 | 
            -
                       | 
| 275 | 
            -
             | 
| 276 | 
            -
             | 
| 277 | 
            -
             | 
| 278 | 
            -
             | 
| 279 | 
            -
             | 
| 280 | 
            -
             | 
| 281 | 
            -
             | 
| 273 | 
            +
                      begin
         | 
| 274 | 
            +
                        add_feed_to_multi(multi, feed_queue.shift, feed_queue, responses, options) unless feed_queue.empty?
         | 
| 275 | 
            +
                        updated_feed = Feed.parse(c.body_str)
         | 
| 276 | 
            +
                        updated_feed.feed_url = c.last_effective_url
         | 
| 277 | 
            +
                        updated_feed.etag = etag_from_header(c.header_str)
         | 
| 278 | 
            +
                        updated_feed.last_modified = last_modified_from_header(c.header_str)
         | 
| 279 | 
            +
                        feed.update_from_feed(updated_feed)
         | 
| 280 | 
            +
                        responses[feed.feed_url] = feed
         | 
| 281 | 
            +
                        options[:on_success].call(feed) if options.has_key?(:on_success)
         | 
| 282 | 
            +
                      rescue Exception => e
         | 
| 283 | 
            +
                        options[:on_failure].call(feed, c.response_code, c.header_str, c.body_str) if options.has_key?(:on_failure)
         | 
| 284 | 
            +
                      end
         | 
| 282 285 | 
             
                    end
         | 
| 283 286 |  | 
| 284 287 | 
             
                    curl.on_failure do |c|
         | 
| @@ -0,0 +1,47 @@ | |
| 1 | 
            +
            module Feedzirra
         | 
| 2 | 
            +
              
         | 
| 3 | 
            +
              module Parser
         | 
| 4 | 
            +
                # == Summary
         | 
| 5 | 
            +
                # Parser for dealing with Atom feeds.
         | 
| 6 | 
            +
                #
         | 
| 7 | 
            +
                # == Attributes
         | 
| 8 | 
            +
                # * prev_page
         | 
| 9 | 
            +
                # * next_page
         | 
| 10 | 
            +
                # * lat_page
         | 
| 11 | 
            +
                # * title
         | 
| 12 | 
            +
                # * subtitle
         | 
| 13 | 
            +
                # * updated
         | 
| 14 | 
            +
                # * feed_url
         | 
| 15 | 
            +
                # * url
         | 
| 16 | 
            +
                # * related
         | 
| 17 | 
            +
                # * entries
         | 
| 18 | 
            +
                class Atom
         | 
| 19 | 
            +
                  include SAXMachine
         | 
| 20 | 
            +
                  include FeedUtilities
         | 
| 21 | 
            +
                  element :"atom:link", :as => :prev_page, :value => :href, :with => {:rel => 'prev'}
         | 
| 22 | 
            +
                  element :"atom:link", :as => :next_page, :value => :href, :with => {:rel => 'next'}
         | 
| 23 | 
            +
                  element :"atom:link", :as => :last_page, :value => :href, :with => {:rel => 'last'}
         | 
| 24 | 
            +
                  element :title
         | 
| 25 | 
            +
                  element :subtitle
         | 
| 26 | 
            +
                  element :updated
         | 
| 27 | 
            +
                  element :link, :as => :url, :value => :href, :with => {:type => "text/html"}
         | 
| 28 | 
            +
                  element :link, :as => :feed_url, :value => :href, :with => {:type => "application/atom+xml"}
         | 
| 29 | 
            +
                  elements :link, :as => :related, :value => :href, :with => {:rel => "related"}
         | 
| 30 | 
            +
                  elements :link, :as => :links, :value => :href
         | 
| 31 | 
            +
                  elements :entry, :as => :entries, :class => AtomEntry
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  def self.able_to_parse?(xml) #:nodoc:
         | 
| 34 | 
            +
                    xml =~ /(Atom)|(#{Regexp.escape("http://purl.org/atom")})/
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
                  
         | 
| 37 | 
            +
                  def url
         | 
| 38 | 
            +
                    @url || links.last
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
                  
         | 
| 41 | 
            +
                  def feed_url
         | 
| 42 | 
            +
                    @feed_url || links.first
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
              
         | 
| 47 | 
            +
            end
         | 
| @@ -0,0 +1,51 @@ | |
| 1 | 
            +
            module Feedzirra
         | 
| 2 | 
            +
              
         | 
| 3 | 
            +
              module Parser
         | 
| 4 | 
            +
                # == Summary
         | 
| 5 | 
            +
                # Parser for dealing with Atom feed entries.
         | 
| 6 | 
            +
                #
         | 
| 7 | 
            +
                # == Attributes
         | 
| 8 | 
            +
                # * title
         | 
| 9 | 
            +
                # * url
         | 
| 10 | 
            +
                # * related
         | 
| 11 | 
            +
                # * author
         | 
| 12 | 
            +
                # * content
         | 
| 13 | 
            +
                # * summary
         | 
| 14 | 
            +
                # * published
         | 
| 15 | 
            +
                # * categories
         | 
| 16 | 
            +
                # * media_content
         | 
| 17 | 
            +
                # * media_description
         | 
| 18 | 
            +
                # * media_thumbnail
         | 
| 19 | 
            +
                # * enclosure
         | 
| 20 | 
            +
                class AtomEntry
         | 
| 21 | 
            +
                  include SAXMachine
         | 
| 22 | 
            +
                  include FeedEntryUtilities
         | 
| 23 | 
            +
                  element :title
         | 
| 24 | 
            +
                  element :link, :as => :url, :value => :href, :with => {:rel => "alternate"}
         | 
| 25 | 
            +
                  elements :link, :as => :related, :value => :href, :with => {:rel => "related"}
         | 
| 26 | 
            +
                  element :name, :as => :author
         | 
| 27 | 
            +
                  element :content
         | 
| 28 | 
            +
                  element :summary
         | 
| 29 | 
            +
                  element :published
         | 
| 30 | 
            +
                  element :id
         | 
| 31 | 
            +
                  element :created, :as => :published
         | 
| 32 | 
            +
                  element :issued, :as => :published
         | 
| 33 | 
            +
                  element :updated
         | 
| 34 | 
            +
                  element :modified, :as => :updated
         | 
| 35 | 
            +
                  elements :category, :as => :categories, :value => :term
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  element :"media:content", :as => :media_content, :value => :url
         | 
| 38 | 
            +
                  element :"media:description", :as => :media_description
         | 
| 39 | 
            +
                  element :"media:thumbnail", :as => :media_thumbnail, :value => :url
         | 
| 40 | 
            +
                  element :enclosure, :value => :url
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  elements :link, :as => :links, :value => :href
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  def url
         | 
| 45 | 
            +
                    @url || links.first
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
              
         | 
| 51 | 
            +
            end
         | 
| @@ -0,0 +1,27 @@ | |
| 1 | 
            +
            module Feedzirra
         | 
| 2 | 
            +
              
         | 
| 3 | 
            +
              module Parser
         | 
| 4 | 
            +
                # == Summary
         | 
| 5 | 
            +
                # Parser for dealing with Feedburner Atom feeds.
         | 
| 6 | 
            +
                #
         | 
| 7 | 
            +
                # == Attributes
         | 
| 8 | 
            +
                # * title
         | 
| 9 | 
            +
                # * feed_url
         | 
| 10 | 
            +
                # * url
         | 
| 11 | 
            +
                # * entries
         | 
| 12 | 
            +
                class AtomFeedBurner
         | 
| 13 | 
            +
                  include SAXMachine
         | 
| 14 | 
            +
                  include FeedUtilities
         | 
| 15 | 
            +
                  element :title
         | 
| 16 | 
            +
                  element :link, :as => :url, :value => :href, :with => {:type => "text/html"}
         | 
| 17 | 
            +
                  element :link, :as => :feed_url, :value => :href, :with => {:type => "application/atom+xml"}
         | 
| 18 | 
            +
                  elements :entry, :as => :entries, :class => AtomFeedBurnerEntry
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  def self.able_to_parse?(xml) #:nodoc:
         | 
| 21 | 
            +
                    (xml =~ /Atom/ && xml =~ /feedburner/) || false
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
              
         | 
| 27 | 
            +
            end
         | 
| @@ -0,0 +1,35 @@ | |
| 1 | 
            +
            module Feedzirra
         | 
| 2 | 
            +
              
         | 
| 3 | 
            +
              module Parser
         | 
| 4 | 
            +
                # == Summary
         | 
| 5 | 
            +
                # Parser for dealing with Feedburner Atom feed entries.
         | 
| 6 | 
            +
                #
         | 
| 7 | 
            +
                # == Attributes
         | 
| 8 | 
            +
                # * title
         | 
| 9 | 
            +
                # * url
         | 
| 10 | 
            +
                # * author
         | 
| 11 | 
            +
                # * content
         | 
| 12 | 
            +
                # * summary
         | 
| 13 | 
            +
                # * published
         | 
| 14 | 
            +
                # * categories
         | 
| 15 | 
            +
                class AtomFeedBurnerEntry
         | 
| 16 | 
            +
                  include SAXMachine
         | 
| 17 | 
            +
                  include FeedEntryUtilities
         | 
| 18 | 
            +
                  element :title
         | 
| 19 | 
            +
                  element :name, :as => :author
         | 
| 20 | 
            +
                  element :link, :as => :url, :value => :href, :with => {:rel => "alternate"}
         | 
| 21 | 
            +
                  element :"feedburner:origLink", :as => :url
         | 
| 22 | 
            +
                  element :summary
         | 
| 23 | 
            +
                  element :content
         | 
| 24 | 
            +
                  element :published
         | 
| 25 | 
            +
                  element :id
         | 
| 26 | 
            +
                  element :issued, :as => :published
         | 
| 27 | 
            +
                  element :created, :as => :published
         | 
| 28 | 
            +
                  element :updated
         | 
| 29 | 
            +
                  element :modified, :as => :updated
         | 
| 30 | 
            +
                  elements :category, :as => :categories, :value => :term
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
                
         | 
| 35 | 
            +
            end
         | 
| @@ -0,0 +1,50 @@ | |
| 1 | 
            +
            module Feedzirra
         | 
| 2 | 
            +
              
         | 
| 3 | 
            +
              module Parser
         | 
| 4 | 
            +
                # iTunes is RSS 2.0 + some apple extensions
         | 
| 5 | 
            +
                # Source: http://www.apple.com/itunes/whatson/podcasts/specs.html
         | 
| 6 | 
            +
                class ITunesRSS
         | 
| 7 | 
            +
                  include SAXMachine
         | 
| 8 | 
            +
                  include FeedUtilities
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  attr_accessor :feed_url
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  # RSS 2.0 elements that need including
         | 
| 13 | 
            +
                  element :copyright
         | 
| 14 | 
            +
                  element :description
         | 
| 15 | 
            +
                  element :language
         | 
| 16 | 
            +
                  element :managingEditor
         | 
| 17 | 
            +
                  element :title
         | 
| 18 | 
            +
                  element :link, :as => :url
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  # If author is not present use managingEditor on the channel
         | 
| 21 | 
            +
                  element :"itunes:author", :as => :itunes_author
         | 
| 22 | 
            +
                  element :"itunes:block", :as => :itunes_block
         | 
| 23 | 
            +
                  element :"itunes:image", :value => :href, :as => :itunes_image
         | 
| 24 | 
            +
                  element :"itunes:explicit", :as => :itunes_explicit
         | 
| 25 | 
            +
                  element :"itunes:keywords", :as => :itunes_keywords
         | 
| 26 | 
            +
                  # New URL for the podcast feed
         | 
| 27 | 
            +
                  element :"itunes:new-feed-url", :as => :itunes_new_feed_url
         | 
| 28 | 
            +
                  element :"itunes:subtitle", :as => :itunes_subtitle
         | 
| 29 | 
            +
                  # If summary is not present, use the description tag
         | 
| 30 | 
            +
                  element :"itunes:summary", :as => :itunes_summary
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  # iTunes RSS feeds can have multiple main categories...
         | 
| 33 | 
            +
                  # ...and multiple sub-categories per category
         | 
| 34 | 
            +
                  # TODO subcategories not supported correctly - they are at the same level
         | 
| 35 | 
            +
                  #   as the main categories
         | 
| 36 | 
            +
                  elements :"itunes:category", :as => :itunes_categories, :value => :text
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  elements :"itunes:owner", :as => :itunes_owners, :class => ITunesRSSOwner
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  elements :item, :as => :entries, :class => ITunesRSSItem
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  def self.able_to_parse?(xml)
         | 
| 43 | 
            +
                    xml =~ /xmlns:itunes=\"http:\/\/www.itunes.com\/dtds\/podcast-1.0.dtd\"/
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
                
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
              
         | 
| 50 | 
            +
            end
         |